#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "sample_comm.h"
#include "sample_vio.h"
#include "./../rtsp/include/rtsp_demo.h"
#include "hh_osd.h"
#include "zstd.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include  "./../rtsp/include/comm.h"
#include "discovery_private_device.h"
#include "thpool.h"
#include "./../udp_transport/udp_transport.h"
#include "./../venc/osd/hh_osd.h"
#include "./../venc/discovery_private_devices/discovery_private_device.h"
#include "./../venc/network/http_init.h"

typedef struct hiSAMPLE_VO_VIDEO_FRAME_STRIDE {
    HI_U32 yStride;
    HI_U32 uStride;
} SAMPLE_VO_VIDEO_FRAME_STRIDE;

#define ALIGN_BACK(x, a) ((a) * (((x) + (a)-1) / (a)))
//#define IMX_335
#define BT_656
#define MAX_FRM_CNT     25
rtsp_demo_handle g_rtsplive = NULL;
rtsp_session_handle session= NULL;
extern int frame_no;
#define WIDTH   1280
#define HEIGHT  512
#define INUPT_PIXEL_FORMAT_YVU PIXEL_FORMAT_YVU_SEMIPLANAR_420

#define RAW_WIDTH   640
#define RAW_HEIGHT  512
#define VI_FRAME_BUFFER_SIZE (RAW_WIDTH * RAW_HEIGHT *  2) // yuv420p/nv12
#define CLAMP(x) ((x) > 255 ? 255 : ((x) < 0 ? 0 : (x)))

VB_BLK g_VbBlk;
GK_U32 g_u32PoolId;

#ifndef __HuaweiLite_
void SAMPLE_VIO_HandleSig(HI_S32 signo)
{
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
    signal(SIGKILL, SIG_IGN);

    if (SIGINT == signo || SIGTERM == signo || SIGKILL == signo)
    {
        SAMPLE_COMM_VENC_StopGetStream();
        SAMPLE_COMM_All_ISP_Stop();
        SAMPLE_COMM_SYS_Exit();

        info("g_VbBlk=%u,g_u32PoolId=%u\n", g_VbBlk, g_u32PoolId);
        if(g_VbBlk >= 0 && g_u32PoolId >= 0)
        {
            HI_MPI_VB_ReleaseBlock(g_VbBlk);
            HI_MPI_VB_MunmapPool(g_u32PoolId);
        }
        err("program termination abnormally!\n");
    }
    exit(-1);
}
#endif

static uint64_t get_current_timestamp_ms() {
    uint64_t timestamp_ms = 0;
    struct timeval tv;
    gettimeofday(&tv, NULL);

    timestamp_ms = (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000;
    return timestamp_ms;
}

#if 1


static inline HI_S32 VIO_bitWidth2PixelFormat(HI_U32 u32Nbit, PIXEL_FORMAT_E *penPixelFormat)
{
    PIXEL_FORMAT_E enPixelFormat;

    if (8 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_8BPP;
    }
    else if (10 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_10BPP;
    }
    else if (12 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_12BPP;
    }
    else if (14 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_14BPP;
    }
    else if (16 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_16BPP;
    }
    else
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_16BPP;
    }

    *penPixelFormat = enPixelFormat;
    return HI_SUCCESS;
}

static HI_S32 VIO_pixelFormat2BitWidth(PIXEL_FORMAT_E *penPixelFormat)
{
    PIXEL_FORMAT_E enPixelFormat;
    enPixelFormat = *penPixelFormat;
    HI_S32 s32BitWidth;

    switch(enPixelFormat)
    {
    case PIXEL_FORMAT_RGB_BAYER_8BPP:
        {
            s32BitWidth = 8;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_10BPP:
        {
            s32BitWidth = 10;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_12BPP:
        {
            s32BitWidth = 12;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_14BPP:
        {
            s32BitWidth = 14;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_16BPP:
        {
            s32BitWidth = 16;
        }
        break;
    default:
        s32BitWidth = HI_FAILURE;
        break;
    }

    return s32BitWidth;
}

HI_S32 VIO_convertBitPixel(HI_U8 *pu8Data, HI_U32 u32DataNum, HI_U32 u32BitWidth, HI_U16 *pu16OutData)
{
    HI_S32 i, u32Tmp, s32OutCnt;
    HI_U32 u32Val;
    HI_U64 u64Val;
    HI_U8 *pu8Tmp = pu8Data;

    s32OutCnt = 0;
    switch(u32BitWidth)
    {
    case 10:
        {
            /* 4 pixels consist of 5 bytes  */
            u32Tmp = u32DataNum / 4;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte4 byte3 byte2 byte1 byte0 */
                pu8Tmp = pu8Data + 5 * i;
                u64Val = pu8Tmp[0] + ((HI_U32)pu8Tmp[1] << 8) + ((HI_U32)pu8Tmp[2] << 16) +
                         ((HI_U32)pu8Tmp[3] << 24) + ((HI_U64)pu8Tmp[4] << 32);

                pu16OutData[s32OutCnt++] = u64Val & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 10) & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 20) & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 30) & 0x3ff;
            }
        }
        break;
    case 12:
        {
            /* 2 pixels consist of 3 bytes  */
            u32Tmp = u32DataNum / 2;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte2 byte1 byte0 */
                pu8Tmp = pu8Data + 3 * i;
                u32Val = pu8Tmp[0] + (pu8Tmp[1] << 8) + (pu8Tmp[2] << 16);
                pu16OutData[s32OutCnt++] = u32Val & 0xfff;
                pu16OutData[s32OutCnt++] = (u32Val >> 12) & 0xfff;
            }
        }
        break;
    case 14:
        {
            /* 4 pixels consist of 7 bytes  */
            u32Tmp = u32DataNum / 4;

            for (i = 0; i < u32Tmp; i++)
            {
                pu8Tmp = pu8Data + 7 * i;
                u64Val = pu8Tmp[0] + ((HI_U32)pu8Tmp[1] << 8) + ((HI_U32)pu8Tmp[2] << 16) +
                         ((HI_U32)pu8Tmp[3] << 24) + ((HI_U64)pu8Tmp[4] << 32) +
                         ((HI_U64)pu8Tmp[5] << 40) + ((HI_U64)pu8Tmp[6] << 48);

                pu16OutData[s32OutCnt++] = u64Val & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 14) & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 28) & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 42) & 0x3fff;
            }
        }
        break;
    case 16:
        {
            /* 1 pixels consist of 2 bytes */
            u32Tmp = u32DataNum;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte1 byte0 */
                pu8Tmp = pu8Data + 2 * i;
                u32Val = pu8Tmp[0] + (pu8Tmp[1] << 8);
                pu16OutData[s32OutCnt++] = u32Val & 0xffff;
            }
        }
        break;
    default:
        fprintf(stderr, "unsupport bitWidth: %d\n", u32BitWidth);
        return HI_FAILURE;
        break;
    }

    return s32OutCnt;
}


HI_S32 VIO_Frame_svFile(VI_PIPE ViPipe,VIDEO_FRAME_S* pVBuf, HI_U32 u32MeshScale, HI_U32 u32ByteAlign, ISP_MESH_SHADING_TABLE_S *pstMLSCTable)
{


    return HI_SUCCESS;

}

#if 0
HI_S32 saveViChnFrameToFile(VIDEO_FRAME_INFO_S  *stVideoFrame, FILE *pFile)
{   
    size_t writeSize = 0;
    // 根据帧的像素格式和尺寸计算数据大小
    size_t dataSize = 0;

    // 如果有UV数据，也需要写入
    if (stVideoFrame->stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) 
    {
        dataSize = stVideoFrame->stVFrame.u32Height * stVideoFrame->stVFrame.u32Stride[0];

        // 写入Y平面数据
        writeSize = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[0]), 1, dataSize, pFile);
        if (writeSize != dataSize) {
            fprintf(stderr, "Failed to write Y plane data to file\n");
        }
        
        dataSize = (stVideoFrame->stVFrame.u32Height / 2) * stVideoFrame->stVFrame.u32Stride[1];
        writeSize = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[1]), 1, dataSize, pFile);
        if (writeSize != dataSize) {
            fprintf(stderr, "Failed to write U plane data to file\n");
        }
        writeSize = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[2]), 1, dataSize, pFile);
        if (writeSize != dataSize) {
            fprintf(stderr, "Failed to write V plane data to file\n");
        }
    }
    else if(stVideoFrame->stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422)
    {
        HI_U32 width = stVideoFrame->stVFrame.u32Width;
        HI_U32 height = stVideoFrame->stVFrame.u32Height;
        HI_U32 yStride = stVideoFrame->stVFrame.u32Stride[0];
        HI_U32 uvStride = stVideoFrame->stVFrame.u32Stride[1];
        HI_U32 writeYszie,writeUszie,writeVszie;
         // 保存Y分量
        for (HI_U32 i = 0; i < height; ++i)
        {
            writeYszie = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[0] + i * yStride), 1, width, pFile);
            fprintf(stdout , "write y data [%d][%d]\n", i, writeYszie);
        }

        // 保存U和V分量
        for (HI_U32 i = 0; i < height / 2; ++i)
        {
            writeUszie = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[1] + i * uvStride), 1, width, pFile);
            writeVszie = fwrite((void *)&(stVideoFrame->stVFrame.u64VirAddr[2] + i * uvStride), 1, width, pFile);
            fprintf(stdout , "write U data [%d][%d]\n", i, writeUszie);
            fprintf(stdout , "write V data [%d][%d]\n", i, writeVszie);
        }


        // if (writeSize != dataSize) {
        //     fprintf(stderr, "Failed to write data to file [%d] [%d]\n", writeSize, dataSize);
        // }
    }
    else{
        fprintf(stderr, "enPixelFormat[%d] unsupport!\n", stVideoFrame->stVFrame.enPixelFormat);
    
    }

    // 关闭文件
    fclose(pFile);
    return HI_SUCCESS;
}
#endif

HI_S32 VIO_VIchn_frame_Save(VIDEO_FRAME_INFO_S          *astFrame, int cnt)
{
    // int                    i, j;
    HI_S32                  s32Ret;
    // HI_S32                 s32MilliSec = 4000;
    // HI_U32                 u32CapCnt = 0;
    // HI_S32                  s32DumpCnt = 0;

    // ISP_MESH_SHADING_TABLE_S  stIspMLSCTable;
    FILE       *pfile = NULL;
    HI_CHAR     name[128] = {0};
    HI_U32      u32Width;
    HI_U32      u32Height;
    HI_U32      u32BitWidth;

    /* dump file */
    u32Width    = astFrame[0].stVFrame.u32Width;
    u32Height   = astFrame[0].stVFrame.u32Height;
    u32BitWidth = 8;//SAMPLE_COMM_VI_PixelFormat2BitWidth(astFrame[0].stVFrame.enPixelFormat);

    snprintf(name, sizeof(name), "/nfs/vi_chn_w%d_h%d_%d.yuv", u32Width, u32Height, cnt);//, u32BitWidth, 
        //SAMPLE_COMM_VI_CompressMode2String(astFrame[0].stVFrame.enCompressMode));
    pfile = fopen(name, "wb");
    if (NULL == pfile)
    {
        SAMPLE_PRT("open file %s fail !\n", name);
        return HI_NULL;
    }

    /* save VI frame to file */
    // saveViChnFrameToFile(&astFrame[0].stVFrame, pfile);
    // VIO_Frame_svFile(ViPipe, &astFrame[0].stVFrame, u32MeshScale, u32ByteAlign, &stIspMLSCTable);

    s32Ret = SAMPLE_COMM_VI_SaveRaw(&astFrame[0].stVFrame, u32BitWidth, pfile);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_SaveRaw failed with %#x!\n", s32Ret);
        goto end;
    }

end:
    if (pfile) {
        fclose(pfile);
        pfile = HI_NULL;
    }
    fprintf(stderr, "save done, s32Ret = [%d] ------Done!\n", s32Ret);

    return HI_SUCCESS;
}

// UDP 发送函数
static void send_via_udp(const char *ip, int port, const char *data, size_t data_len) {
    int sockfd;
    struct sockaddr_in server_addr;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        return;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(ip);

    sendto(sockfd, data, data_len, 0, (const struct sockaddr *) &server_addr, sizeof(server_addr));

    close(sockfd);
}


#if 0
HI_S32 get_vichn_raw_date_sendto_venc(VIDEO_FRAME_INFO_S  *astFrame, VENC_CHN VeChn, FILE* file)
{
    int                    i, j;
    HI_S32                  s32Ret;
    HI_S32                 s32MilliSec = 4000;
    HI_U32                 u32CapCnt = 0;
    HI_S32                  s32DumpCnt = 0;

    FILE       *pfile = NULL;
    HI_CHAR     name[128] = {0};
    HI_U32      u32Width;
    HI_U32      u32Height;
    HI_U32      u32BitWidth;

    /* dump file */
    u32Width    = astFrame[0].stVFrame.u32Width;
    u32Height   = astFrame[0].stVFrame.u32Height;
    u32BitWidth = 8;//SAMPLE_COMM_VI_PixelFormat2BitWidth(astFrame[0].stVFrame.enPixelFormat);

    // s32Ret = SAMPLE_COMM_VI_SaveRaw(&astFrame[0].stVFrame, u32BitWidth, pfile);

    HI_U32  u64Ret = 0, u32Size = (astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height * 3 / 2);
    HI_U64  u64PhyAddr;
    HI_U64  u64Size;
    HI_U8  *pu8VirAddr;
    HI_U16 *pu16Data = NULL;
    HI_U8  *pu8Data;
    PIXEL_FORMAT_E enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FRAME_INFO_S *stFrmInfo = (VIDEO_FRAME_INFO_S *)astFrame;
    HI_U32 u32UvSize = (astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height / 2);
    if (enPixelFormat != astFrame[0].stVFrame.enPixelFormat)
    {
        printf("invalid pixel format:%d[%d], u32Nbit: %d\n",  astFrame[0].stVFrame.enPixelFormat, enPixelFormat, u32BitWidth);
        // return HI_FAILURE;
    }

    u64PhyAddr = astFrame[0].stVFrame.u64PhyAddr[0];
    // astFrame[0].enModId = MOD_ID_VENC;
    // static uint64_t ref_time_index = 0;
    // ref_time_index += 2;
    // astFrame[0].stVFrame.u32TimeRef = ref_time_index;
    // astFrame[0].stVFrame.u64PTS     += ref_time_index;

    // printf("pix_fmt(%d)[%d], wh(%d, %d)[%d], u32Nbit(%d), u32Size[%d], u32Field[%d], poolId[%d], u32TimeRef[%d], enModId[%d],\
    // enVideoFormat[%d], pts[%llu]\n",enPixelFormat,\
    //      stFrmInfo[0].stVFrame.enPixelFormat, stFrmInfo[0].stVFrame.u32Width, stFrmInfo[0].stVFrame.u32Height, stFrmInfo[0].stVFrame.u32Stride[0], \
    //      u32BitWidth, u32Size , stFrmInfo[0].stVFrame.enField, stFrmInfo[0].u32PoolId ,stFrmInfo[0].stVFrame.u32TimeRef,stFrmInfo[0].enModId ,\
    //     stFrmInfo[0].stVFrame.enVideoFormat, stFrmInfo[0].stVFrame.u64PTS);


    pu8VirAddr = (HI_U8 *) HI_MPI_SYS_Mmap(u64PhyAddr, u32Size);//u64Size
    if (NULL == pu8VirAddr)
    {
        SAMPLE_PRT("HI_MPI_SYS_Mmap fail !\n");
        // HI_MPI_VB_ReleaseBlock(VbBlk);
        return HI_FAILURE;
    }

    pu8Data = pu8VirAddr;
    if ((8 != u32BitWidth) && (16 != u32BitWidth))
    {
        pu16Data = (HI_U16 *)malloc(astFrame[0].stVFrame.u32Width * 2U);
        if (NULL == pu16Data)
        {
            SAMPLE_PRT("alloc memory failed\n");
            goto END;
        }
    }

    // uint64_t current_time = get_current_timestamp_ms();
    // printf("saving......dump data......u32Stride[0]: %d, width: %d\n", stFrmInfo[0].stVFrame.u32Stride[0], stFrmInfo[0].stVFrame.u32Width);
    
    char vi_frame_buffer[VI_FRAME_BUFFER_SIZE] = {0};
    size_t frame_size;
    size_t compressed_buffer_size = ZSTD_compressBound(VI_FRAME_BUFFER_SIZE);
    char *compressed_buffer = malloc(compressed_buffer_size);

    if (compressed_buffer == NULL) {
        fprintf(stderr, "Failed to allocate memory for compression buffer\n");
        goto END;
    }
    // 压缩帧数据
    fprintf(stderr, "compressed_buffer_size = [%d] Done!\n", compressed_buffer_size);
    uint64_t current_time = get_current_timestamp_ms();

    memcpy(vi_frame_buffer, pu8Data, u32Size);
    size_t compressed_size = 0;
    compressed_size = ZSTD_compress(compressed_buffer, compressed_buffer_size, vi_frame_buffer, u32Size, 1);
    if (ZSTD_isError(compressed_size)) {
        fprintf(stderr, "ZSTD compression error: %s\n", ZSTD_getErrorName(compressed_size));
        goto END;
    }
    uint64_t current_time2 = get_current_timestamp_ms();
    // 通过 UDP 发送压缩后的数据
    // send_via_udp("192.168.110.171", 12345, compressed_buffer, compressed_size);

    FILE *fpRaw = fopen("/nfs/test_data.yuv", "w");
    if (!fpRaw) {
        perror("Failed to open output file");
        goto END;
    }

    static int ii = 0;
    if(0 == ii)
    {
        fwrite(vi_frame_buffer, u32Size, 1, fpRaw);
        // fwrite(pu8Data, u32Size, 1, file);
        fclose(fpRaw);
    }
    ++ii;

    if (NULL != pu16Data)
    {
        free(pu16Data);
    }
    HI_MPI_SYS_Munmap(pu8VirAddr, u32Size);//u64Size
    pu8VirAddr = NULL;
   
    fprintf(stderr, "save done, s32Ret = [%d] compressed_size[%d] 压缩比：%f,耗时：%llu ms------Done!\n", s32Ret, compressed_size, \
    (float)(compressed_size)/(float)(compressed_buffer_size), current_time2-current_time);

    return HI_SUCCESS;
END:
    HI_MPI_SYS_Munmap(pu8VirAddr, u32Size);//u64Size
    pu8VirAddr = NULL;
    return HI_FAILURE;
}
#endif

HI_S32 VIO_Dump_Proc(VI_PIPE ViPipe, HI_U32 u32MeshScale, HI_U32 u32Cnt, HI_U32 u32ByteAlign, HI_U32 u32RatioShow)
{
    int                     i, j;
    HI_S32                  s32Ret;
    HI_S32                  s32MilliSec = 4000;
    HI_U32                  u32CapCnt = 0;
    HI_S32                  s32DumpCnt = 0;
    VI_CMP_PARAM_S          stCmpPara;
    VIDEO_FRAME_INFO_S      astFrame[MAX_FRM_CNT];
    ISP_MESH_SHADING_TABLE_S  stIspMLSCTable;
    FILE                    *pfile = NULL;
    HI_CHAR                 name[128] = {0};
    HI_U32                  u32Width;
    HI_U32                  u32Height;
    HI_U32                  u32BitWidth;

    /* get VI frame */
    for (i = 0; i < u32Cnt; i++)
    {
        s32Ret = HI_MPI_VI_GetPipeFrame(ViPipe, &astFrame[i], s32MilliSec);
        if (HI_SUCCESS != s32Ret)
        {
            printf("get vi Pipe %d frame err, s32Ret = [0x%x].\n", ViPipe, s32Ret);
            printf("only get %d frame\n", i);
            break;
        }

        printf("get vi Pipe %d frame num %d ok\n", ViPipe, i);
    }

    u32CapCnt = i;

    if (0 == u32CapCnt)
    {
        return HI_FAILURE;
    }

    //testIspDngInfo(ViPipe, &stFrame);

    //HI_MPI_VI_ReleasePipeFrame(ViPipe, &stFrame);

    if (COMPRESS_MODE_NONE != astFrame[0].stVFrame.enCompressMode)
    {
        if (HI_SUCCESS != HI_MPI_VI_GetPipeCmpParam(ViPipe, &stCmpPara))
        {
            SAMPLE_PRT("HI_MPI_VI_GetPipeCmpParam failed with %#x!\n", s32Ret);
            goto end;
        }

        SAMPLE_COMM_VI_SaveCompressParam(&stCmpPara, pfile);
    }

    /* dump file */
    u32Width    = astFrame[0].stVFrame.u32Width;
    u32Height   = astFrame[0].stVFrame.u32Height;
    u32BitWidth = SAMPLE_COMM_VI_PixelFormat2BitWidth(astFrame[0].stVFrame.enPixelFormat);

    snprintf(name, sizeof(name), "/mnt/dump_pipe%d_w%d_h%d_%dbits_%s_25.raw", ViPipe, u32Width,
        u32Height, u32BitWidth, SAMPLE_COMM_VI_CompressMode2String(astFrame[0].stVFrame.enCompressMode));
    pfile = fopen(name, "ab");
    if (NULL == pfile)
    {
        SAMPLE_PRT("open file %s fail !\n", name);
        return HI_NULL;
    }

    for (j = 0; j < u32CapCnt; j++)
    {
        /* save VI frame to file */
        //VIO_Frame_svFile(ViPipe, &astFrame[j].stVFrame, u32MeshScale, u32ByteAlign, &stIspMLSCTable);

        s32Ret = SAMPLE_COMM_VI_SaveRaw(&astFrame[0].stVFrame, u32BitWidth, pfile);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SaveRaw failed with %#x!\n", s32Ret);
            goto end;
        }

        s32DumpCnt++;

        /* release frame after using */
        HI_MPI_VI_ReleasePipeFrame(ViPipe, &astFrame[j]);
    }

end:
    if (pfile) {
        fclose(pfile);
        pfile = HI_NULL;
    }
    fprintf(stderr, "s32DumpCnt = [%d] ------Done!\n", s32DumpCnt);

    return HI_SUCCESS;
}

static HI_VOID* send_ztsd_data_to_user(HI_VOID* thread_arg)
{
    SendZstdData_S *data_arg = (SendZstdData_S *)thread_arg;
  
    if(!data_arg || !(data_arg->pu8VirAddr_uv) || (data_arg->uv_size) <= 0)
    {
        err("input pu8VirAddr_uv or uv_size ERR!\n");
        goto END;
    }
    
    pthread_mutex_lock(&data_arg->mutex);
    // info("thread %d start!, uv_addr=%x, mutex=%d, uv_size=%u.\n", data_arg->thread_count, data_arg->pu8VirAddr_uv, data_arg->mutex, data_arg->uv_size);
    
    // char vi_frame_buffer[VI_FRAME_BUFFER_SIZE] = {0};
#ifdef ZSTD_COMPRESS
    size_t compressed_buffer_size = ZSTD_compressBound(VI_FRAME_BUFFER_SIZE);

    char *compressed_buffer = malloc(compressed_buffer_size);

    if (compressed_buffer == NULL) {
        fprintf(stderr, "Failed to allocate memory for compression buffer\n");
        goto END;
    }

    // 压缩帧数据
    // info("compressed_buffer_size = [%d] Done!\n", compressed_buffer_size);
    uint64_t current_time = get_current_timestamp_ms();

    // memcpy(vi_frame_buffer, data_arg->pu8VirAddr_uv, data_arg->uv_size);

    size_t compressed_size = 0;
    compressed_size = ZSTD_compress(compressed_buffer, compressed_buffer_size, data_arg->pu8VirAddr_uv, data_arg->uv_size, 1);
    if (ZSTD_isError(compressed_size)) {
        fprintf(stderr, "ZSTD compression error: %s\n", ZSTD_getErrorName(compressed_size));
        free(compressed_buffer);
        compressed_buffer = NULL;
        goto END;
    }
#else
    size_t compressed_buffer_size = LZ4_compressBound(VI_FRAME_BUFFER_SIZE);
    char *compressed_buffer = malloc(compressed_buffer_size);

    if (compressed_buffer == NULL) {
        fprintf(stderr, "Failed to allocate memory for compression buffer\n");
        goto END;
    }

    // 压缩帧数据
    uint64_t current_time = get_current_timestamp_ms();
    size_t compressed_size = 0;
    compressed_size = LZ4_compress_default(data_arg->pu8VirAddr_uv, compressed_buffer, compressed_buffer_size, data_arg->uv_size);
    // compressed_size = LZ4_compress_fast(data_arg->pu8VirAddr_uv, compressed_buffer, compressed_buffer_size ,data_arg->uv_size, 10);
    if (compressed_size <= 0) {
    //     printf("压缩成功，压缩后的大小：%d\n", compressed_size);
    // } else {
        printf("压缩失败！\n");
    }
#endif

    uint64_t current_time2 = get_current_timestamp_ms();
    // err("save done耗时: %llu  ms------Done!\n", current_time2 - current_time);
    // 通过 UDP 发送压缩后的数据
    // send_via_udp("192.168.110.194", 9527, compressed_buffer, compressed_size);
    // 将压缩数据添加到队列
    enqueue((char *)compressed_buffer, compressed_size);

#ifndef SAVE_FILE
    static int ii = 0;
    if(1 == ii)
    {
        FILE *fpRaw = fopen("/nfs/test_out_data.yuv", "w");
        if (!fpRaw) {
            perror("Failed to open output file");
            free(compressed_buffer);
            compressed_buffer = NULL;
            goto END;
        }

        // fwrite(data_arg->pu8VirAddr_uv, data_arg->uv_size, 1, fpRaw);
        fwrite(compressed_buffer, compressed_size, 1, fpRaw);
        fclose(fpRaw);
    }
   
    ++ii;
 #endif  
    
    uint64_t last_time = get_current_timestamp_ms();
    // info("save done,[%02x %02x %02x %02x]  compressed_size[%d] 压缩比：%f,耗时：%llu ms,存文件耗时 %llu ms------Done!\n",compressed_buffer[0],compressed_buffer[1],compressed_buffer[2],compressed_buffer[3],  compressed_size, \
    // (float)(compressed_size)/(float)(compressed_buffer_size), current_time2-current_time, last_time - current_time2);
    free(compressed_buffer);
    compressed_buffer = NULL;

    // info("thread %d end!\n", data_arg->thread_count);
    pthread_mutex_unlock(&data_arg->mutex);
    // free(data_arg->pu8VirAddr_uv);
    return NULL;
END:
    // info("thread %d end!!!\n", data_arg->thread_count);
    pthread_mutex_unlock(&data_arg->mutex);
    // free(data_arg->pu8VirAddr_uv);
    return NULL;
}

HI_S32 VIO_getDumpPipe(VI_DEV ViDev, WDR_MODE_E enInWDRMode, HI_U32 *pu32PipeNum, VI_PIPE ViPipeId[])
{
    HI_S32 s32Ret;
    HI_U32 u32PipeNum, i;
    VI_DEV_BIND_PIPE_S stDevBindPipe;

    memset(&stDevBindPipe, 0, sizeof(stDevBindPipe));
    s32Ret = HI_MPI_VI_GetDevBindPipe(ViDev, &stDevBindPipe);
    if (HI_SUCCESS != s32Ret)
    {
        printf("HI_MPI_VI_GetDevBindPipe error 0x%x !\n", s32Ret);
        return s32Ret;
    }

    u32PipeNum = 0;

    switch (enInWDRMode)
    {
        case WDR_MODE_NONE:
        case WDR_MODE_BUILT_IN:
            if (stDevBindPipe.u32Num < 1)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 1;
            ViPipeId[0] = stDevBindPipe.PipeId[0];
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        case WDR_MODE_2To1_LINE:
        case WDR_MODE_2To1_FRAME:
        case WDR_MODE_2To1_FRAME_FULL_RATE:
            if (2 != stDevBindPipe.u32Num)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 2;
            for (i = 0; i < u32PipeNum; i++)
            {
                ViPipeId[i] = stDevBindPipe.PipeId[i];
            }
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        default:
            printf("enInWDRMode(%d) error !\n", enInWDRMode);
            return HI_FAILURE;
    }

    *pu32PipeNum = u32PipeNum;

    return HI_SUCCESS;
}


void SAMPLE_DUMP_Proc()
{
    VI_DEV            ViDev                = 0;
    VI_PIPE           ViPipe               = 0;
    VI_PIPE           ViPipeId[4]          = {0};  /* save main pipe to [4] */
    HI_S32            s32Ret               = 0;
    HI_U32            i                    = 0;
    HI_U32            u32FrmCnt            = 1;
    HI_U32            u32RawDepth          = 2;
    HI_U32            u32ByteAlign         = 1;
    HI_U32            u32PipeNum           = 2;   /* LineMode -> 1, WDRMode -> 2~3 */
    HI_U32            u32RatioShow         = 1;
    HI_U32            u32MeshScale         = 6;//1;
    COMPRESS_MODE_E   enCompressMode       = COMPRESS_MODE_NONE;
    VI_DUMP_ATTR_S    stRawDumpAttr, stRawDumpAttrCheck;
    VI_DUMP_ATTR_S    stDumpAttr;
    VI_DEV_ATTR_S     stDevAttr;
    VI_PIPE_ATTR_S    astBackUpPipeAttr[4];
    VI_PIPE_ATTR_S    stPipeAttr;

    //enCompressMode = COMPRESS_MODE_NONE; /* non_compress_mode */
    u32FrmCnt      = 1;  /* frame number is 1 */
    u32ByteAlign   = 1;  /* convert to Byte align */
    u32RatioShow   = 0;  /* ratio not shown */

    if (1 > u32FrmCnt || MAX_FRM_CNT < u32FrmCnt)
    {
        printf("invalid FrmCnt %d, FrmCnt range from 1 to %d\n", u32FrmCnt, MAX_FRM_CNT);
        exit(HI_FAILURE);
    }

    s32Ret = HI_MPI_VI_GetDevAttr(ViDev, &stDevAttr);

    if (HI_SUCCESS != s32Ret)
    {
        printf("Get dev %d attr failed!\n", ViDev);
        goto EXIT;
    }

    s32Ret = VIO_getDumpPipe(ViDev, stDevAttr.stWDRAttr.enWDRMode, &u32PipeNum, ViPipeId);

    if (HI_SUCCESS != s32Ret)
    {
        printf("getDumpPipe failed 0x%x!\n", s32Ret);
        goto EXIT;
    }

    printf("Setting Parameter ==> MeshScale =%d, u32PipeNum = [%d].\n", u32MeshScale, u32PipeNum);

    for (i = 0; i < u32PipeNum; i++)
    {
        s32Ret = HI_MPI_VI_GetPipeDumpAttr(ViPipeId[i], &stRawDumpAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Get Pipe %d dump attr failed!\n", ViPipe);
            goto EXIT;
        }

        memcpy(&stDumpAttr, &stRawDumpAttr, sizeof(VI_DUMP_ATTR_S));
        stDumpAttr.bEnable                       = HI_TRUE;
        stDumpAttr.u32Depth                      = u32RawDepth;
        stDumpAttr.enDumpType                    = VI_DUMP_TYPE_RAW;
        s32Ret = HI_MPI_VI_SetPipeDumpAttr(ViPipeId[i], &stDumpAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d dump attr failed!\n", ViPipeId[i]);
            goto EXIT;
        }

        memset(&stRawDumpAttrCheck, 0x0, sizeof(stRawDumpAttrCheck));
        s32Ret = HI_MPI_VI_GetPipeDumpAttr(ViPipeId[i], &stRawDumpAttrCheck);
        if (HI_SUCCESS != s32Ret)
        {
            printf("Get Pipe %d dump attr failed!\n", ViPipe);
            goto EXIT;
        }

        printf("Get Pipe %d dump attr Type;%d, bEnable:%d, u32Depth:%d!\n", ViPipe, stRawDumpAttrCheck.enDumpType, stRawDumpAttrCheck.bEnable, stRawDumpAttrCheck.u32Depth);

        s32Ret = HI_MPI_VI_GetPipeAttr(ViPipeId[i], &astBackUpPipeAttr[i]);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Get Pipe %d attr failed!\n", ViPipe);
            goto EXIT;
        }

        memcpy(&stPipeAttr, &astBackUpPipeAttr[i], sizeof(VI_PIPE_ATTR_S));
        stPipeAttr.enCompressMode = enCompressMode;
        s32Ret = HI_MPI_VI_SetPipeAttr(ViPipeId[i], &stPipeAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d attr failed!\n", ViPipe);
            goto EXIT;
        }
    }

    sleep(1);
    printf("--> u32PipeNum=%d\n", u32PipeNum);

    if (1 == u32PipeNum || 1 == u32FrmCnt)
    {
        VIDEO_FRAME_INFO_S      astFrame[MAX_FRM_CNT];

        // VIO_Dump_Proc( ViPipe,  u32MeshScale,  u32Cnt,  u32ByteAlign,  u32RatioShow);
        i = 0;

        s32Ret = HI_MPI_VI_GetPipeFrame(ViPipe, &astFrame[i], 1000);
        if (HI_SUCCESS != s32Ret)
        {
            err("HI_MPI_VI_GetPipeFrame Pipe %d attr failed ret:%#x!\n", ViPipe, s32Ret);
            goto EXIT;
        }

        s32Ret = HI_MPI_VI_ReleasePipeFrame(ViPipe, &astFrame[i]);
        if (HI_SUCCESS != s32Ret)
        {
            err("HI_MPI_VI_ReleasePipeFrame Pipe %d attr failed ret:%#x!\n", ViPipe, s32Ret);
            goto EXIT;
        }
    }
    else
    {
        printf("Please check if PipeNum is equal to 1!\n");
        goto EXIT;
    }


EXIT:
    return s32Ret;
}

HI_S32 SAMPLE_VIO_ViOnlineVpssOffline(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN1;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    ISP_DIS_ATTR_S     stDISAttr;
    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);

    if (stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType == BT656_2M_30FPS_8BIT)
    {
        stSize.u32Width = 720;
        stSize.u32Height = 288;
    }

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 1;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 2;

    // u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    // stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    // stVbConf.astCommPool[0].u32BlkCnt   = 3;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    //HI_MPI_VI_SetPipeDumpAttr();

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width-100;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height-100;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[VPSS_CHN1] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    VPSS_CROP_INFO_S stVpssCropInfo;

    stVpssCropInfo.bEnable = HI_TRUE;
    stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
    stVpssCropInfo.stCropRect.s32X = 50;
    stVpssCropInfo.stCropRect.s32Y = 50;
    stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width-100;
    stVpssCropInfo.stCropRect.u32Height = stSize.u32Height-100;
    s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.u32DisBufLen = 3;

    stVoConfig.enPicSize = enPicSize;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    printf("Enter any key to enable 2Dim-Dis.\n");
    PAUSE();
    stDISAttr.bEnable = HI_TRUE;
    HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);

    printf("Enter any key to Disable 2Dim-Dis.\n");
    PAUSE();
    stDISAttr.bEnable = HI_FALSE;
    HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);
    PAUSE();

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT3:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

HI_S32 SAMPLE_VIO_ViOnlineVpssOnlineRoute1(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_ONLINE;//VI_OFFLINE_VPSS_OFFLINE;//

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VENC_CHN           VencChn[1]  = {0};
    PAYLOAD_TYPE_E     enType      = PT_H265;
    SAMPLE_RC_E        enRcMode    = SAMPLE_RC_CBR;
    HI_U32             u32Profile  = 0;
    HI_BOOL            bRcnRefShareBuf = HI_TRUE;
    VENC_GOP_ATTR_S    stGopAttr;

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    //SAMPLE_PRT("[uyvy]: stSize.w/h = (%d, %d) !\n", stSize.u32Width, stSize.u32Height);
    SAMPLE_PRT("[uyvy]: stSize.w/h = (%d, %d) - [%d, %d]!\n", stSize.u32Width, stSize.u32Height, IN_WIDTH, IN_HEIGHT);

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 1;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 3;

    u32BlkSize = COMMON_GetPicBufferSize(720, 576, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    //u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 5;


    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/

    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = COMPRESS_MODE_SEG;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    astVpssChnAttr[VPSS_CHN1].u32Width                    = stSize.u32Width;//720;
    astVpssChnAttr[VPSS_CHN1].u32Height                   = stSize.u32Height;//576;
    astVpssChnAttr[VPSS_CHN1].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VPSS_CHN1].enCompressMode              = enCompressMode;
    astVpssChnAttr[VPSS_CHN1].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VPSS_CHN1].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VPSS_CHN1].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].u32Depth                    = 0;
    astVpssChnAttr[VPSS_CHN1].bMirror                     = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].bFlip                       = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    abChnEnable[1] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    VPSS_CROP_INFO_S stVpssCropInfo;

    stVpssCropInfo.bEnable = HI_TRUE;
    stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
    stVpssCropInfo.stCropRect.s32X = 50;
    stVpssCropInfo.stCropRect.s32Y = 50;
    stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width-100;
    stVpssCropInfo.stCropRect.u32Height = stSize.u32Height-100;
    s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

#if 0
// #else
    SAMPLE_DUMP_Proc();
    // SAMPLE_COMM_VI_StartDumpRawThread(ViPipe, 50, "vot");
    SAMPLE_PRT("Start Dump Raw Thread().\n");
    sleep(5);
    SAMPLE_PRT("Dump Raw Thread() done.\n");
    SAMPLE_COMM_VI_StopDumpRawThread();
#endif

    /*config venc */
    stGopAttr.enGopMode  = VENC_GOPMODE_NORMALP; //VENC_GOPMODE_SMARTP
    stGopAttr.stNormalP.s32IPQpDelta = 2;
    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enType, enPicSize, enRcMode, u32Profile,bRcnRefShareBuf, &stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start venc failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn[0]);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc bind Vpss failed. s32Ret: 0x%x !n", s32Ret);
        goto EXIT3;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.u32DisBufLen = 0;
    stVoConfig.enPicSize = enPicSize;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VPSS_CHN0, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT5;
    }

    s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, sizeof(VencChn)/sizeof(VENC_CHN));
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Get venc stream failed!\n");
        goto EXIT6;
    }

    PAUSE();

    SAMPLE_COMM_VENC_StopGetStream();

    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
EXIT6:
    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VPSS_CHN1, stVoConfig.VoDev, VoChn);
EXIT5:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT4:
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn[0]);
EXIT3:
    SAMPLE_COMM_VENC_Stop(VencChn[0]);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}


#endif




// BMP header size is 54 bytes
#define BMP_HEADER_SIZE 54

// int read_bmp_rgb(const char *bmp_file, unsigned char *rgb_data) {
//     FILE *file = fopen(bmp_file, "rb");
//     if (!file) {
//         err("Unable to open file %s\n", bmp_file);
//         return -1;
//     }

//     // Skip BMP header (54 bytes)
//     fseek(file, BMP_HEADER_SIZE, SEEK_SET);

//     // Read RGB data
//     size_t rgb_size = WIDTH * HEIGHT * 3; // Each pixel has 3 bytes (RGB)
//     if (fread(rgb_data, 1, rgb_size, file) != rgb_size) {
//         err("Failed to read BMP data\n");
//         fclose(file);
//         return -1;
//     }

//     fclose(file);
//     return 0;
// }

#include "mpi_ive.h" // HiSilicon IVE interface
// #include <stdio.h>
// #include <string.h>

// #define WIDTH 640
// #define HEIGHT 512

// 初始化 IVE 模块
// void init_ive() {
//     HI_MPI_IVE_Init();
// }

// 转换 RGB 数据到 YUV 数据
int convert_rgb_to_yuv(unsigned char *rgb_data, unsigned char *yuv_data) {
    IVE_HANDLE hIveHandle;
    IVE_IMAGE_S stSrcImg;  // 输入 RGB 图像
    IVE_IMAGE_S stDstImg;  // 输出 YUV 图像
    IVE_CSC_CTRL_S stCscCtrl;
    HI_BOOL        bFinish;
    unsigned int imgSize = 640*512*3/2;

    // 设置输入图像结构体 (RGB)
    memset(&stSrcImg, 0, sizeof(IVE_IMAGE_S));
    stSrcImg.enType = IVE_IMAGE_TYPE_U8C3_PACKAGE; // RGB 打包格式
    stSrcImg.u32Width = WIDTH;
    stSrcImg.u32Height = HEIGHT;
    stSrcImg.au64VirAddr[0] = (HI_U64)(HI_UL)rgb_data; // 输入 RGB 数据地址
    stSrcImg.au64PhyAddr[0] = 0;  // 物理地址（非必要）

    // 设置输出图像结构体 (YUV)
    memset(&stDstImg, 0, sizeof(IVE_IMAGE_S));
    stDstImg.enType = IVE_IMAGE_TYPE_YUV420SP; // YUV 420 格式
    stDstImg.u32Width = WIDTH;
    stDstImg.u32Height = HEIGHT;
    stDstImg.au64VirAddr[0] = (HI_U64)(HI_UL)yuv_data;  // 输出 Y 数据地址
    stDstImg.au64VirAddr[1] = (HI_U64)(HI_UL)(yuv_data + WIDTH * HEIGHT);  // 输出 UV 数据地址
    stDstImg.au64PhyAddr[0] = 0;  // 物理地址（非必要）
    stDstImg.au64PhyAddr[1] = 0;


    int ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstImg.au64PhyAddr[0],(HI_VOID**)&stDstImg.au64VirAddr[0],"User", HI_NULL, imgSize);

    if(HI_SUCCESS != ret)
    {
        HI_MPI_SYS_MmzFree(stSrcImg.au64PhyAddr[0],(HI_VOID**)stSrcImg.au64VirAddr[0]);
        err("HI_MPI_SYS_MmzAlloc_Cached Failed!");
        return -1;
    }

    memset((HI_VOID**)stDstImg.au64VirAddr[0], 0, stDstImg.u32Height*stDstImg.au32Stride[0]);
    ret = HI_MPI_SYS_MmzFlushCache(stDstImg.au64PhyAddr[0],(HI_VOID**)stDstImg.au64VirAddr[0],stDstImg.u32Height*stDstImg.au32Stride[0]);
    if(HI_SUCCESS !=ret)
    {
        HI_MPI_SYS_MmzFree(stDstImg.au64PhyAddr[0],(HI_VOID**)stDstImg.au64VirAddr[0]);
        printf("HI_MPI_SYS_MmzFlushCache Failed!");
        return -1;
    }
   
    // 设置颜色转换控制结构体
    memset(&stCscCtrl, 0, sizeof(IVE_CSC_CTRL_S));
    stCscCtrl.enMode = IVE_CSC_MODE_VIDEO_BT601_YUV2RGB;

    // 执行颜色空间转换
    HI_S32 s32Ret = HI_MPI_IVE_CSC(&hIveHandle, &stSrcImg, &stDstImg, &stCscCtrl, HI_TRUE);
    if (s32Ret != HI_SUCCESS) {
        err("HI_MPI_IVE_CSC failed with error code: 0x%x\n", s32Ret);
        HI_MPI_SYS_MmzFree(stDstImg.au64PhyAddr[0],(HI_VOID**)stDstImg.au64VirAddr[0]);
        return -1;
    }

    // 等待任务完成
    s32Ret = HI_MPI_IVE_Query(hIveHandle, &bFinish, HI_TRUE);
    if (s32Ret != HI_SUCCESS){
        err("HI_MPI_IVE_Query failed with error code %#x\n", s32Ret);
    }
    
    HI_MPI_SYS_MmzFlushCache(stDstImg.au64PhyAddr[0],(void **) stDstImg.au64VirAddr[0], imgSize);

    memcpy((void *) (yuv_data), (void *) stDstImg.au64VirAddr[0], imgSize);
    // HI_MPI_SYS_Munmap((HI_VOID *) g_sys_conf.stSrc_yvu420_packet.au64VirAddr[0], u32DstBlkSize / 2);
    
    return 0;
}

// RGB to YUV conversion
void RGBtoYUV(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v) {
    // BT.601
    *y = CLAMP((uint8_t)(0.299 * r + 0.587 * g + 0.114 * b));
    *u = CLAMP((uint8_t)(-0.14713 * r - 0.28886 * g + 0.436 * b + 128));
    *v = CLAMP((uint8_t)(0.615 * r - 0.51499 * g - 0.10001 * b + 128));

    //BT.709
    // *y = CLAMP((uint8_t)(0.2126 * r + 0.7152 * g + 0.0722 * b));
    // *u = CLAMP((uint8_t)(-0.1146 * r - 0.3854 * g + 0.5000 * b + 128));
    // *v = CLAMP((uint8_t)(0.5000 * r - 0.4542 * g - 0.0458 * b + 128));
}

// Function to convert RGB to YUV420 and store in buffer
void RGBtoYUV420(uint8_t *rgbBuffer, uint8_t *yuvBuffer, int width, int height) {
    int y_index = 0;
    int uv_index = width * height;

    for (int j = height - 1; j >= 0; j--) {
        for (int i = 0; i < width; i++) {
            uint8_t r = rgbBuffer[(j * width + i) * 3];
            uint8_t g = rgbBuffer[(j * width + i) * 3 + 1];
            uint8_t b = rgbBuffer[(j * width + i) * 3 + 2];

            uint8_t y, u, v;

            RGBtoYUV(r, g, b, &y, &u, &v);

            // Store Y value
            yuvBuffer[y_index++] = y;

            // Store U and V only for even rows and columns (2x2 block)
            if (j % 2 == 0 && i % 2 == 0) {
                yuvBuffer[uv_index++] = v;
                yuvBuffer[uv_index++] = u;
            }
        }
    }
}

static int  convert_rgb_to_yuv_self(char* filename, void*rgbBuffer, void* yuvBuffer , int width, int height ) {
    FILE *inputFile = fopen(filename, "rb"); // RGB input file
   
    if (inputFile == NULL ) {
        printf("Error opening file!\n");
        return 1;
    }

    int rgbSize = width * height * 3;
    int yuvSize =  width * height * 3 / 2;
    // Assuming 24-bit RGB (R, G, B each 1 byte)

    // 读取BMP头并跳过
    unsigned char bmp_header[BMP_HEADER_SIZE];
    fread(bmp_header, 1, BMP_HEADER_SIZE, inputFile);

    fread(rgbBuffer, sizeof(uint8_t), rgbSize, inputFile);
    
    RGBtoYUV420(rgbBuffer, yuvBuffer, width, height);

    fclose(inputFile);

    printf("RGB to YUV conversion completed.\n");
    return 0;
}
   
void rgb_to_yuv(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v) {
    *y = (uint8_t)(0.299 * r + 0.587 * g + 0.114 * b);
    *u = (uint8_t)(-0.14713 * r - 0.28886 * g + 0.436 * b + 128);
    *v = (uint8_t)(0.615 * r - 0.51499 * g - 0.10001 * b + 128);
}

void rgb_to_nv12(uint8_t *rgbBuffer, RGBQuad palette[256] ,uint8_t *yuvBuffer, int width, int height)
{
    // NV12分配内存
    // uint8_t *nv12Data = (uint8_t *)malloc(width * height + (width * height) / 2);
    int y_index = 0;
    int uv_index = width * height;  // UV 平面从 Y 平面的末尾开始

    // 遍历像素数据并转换为YUV
    for (int y = height; y > 0; y--) {
        for (int x = 0; x < width; x++) {
            uint8_t colorIndex = rgbBuffer[y * width + x];
            RGBQuad color = palette[colorIndex];
            uint8_t Y, U, V;
            rgb_to_yuv(color.rgbRed, color.rgbGreen, color.rgbBlue, &Y, &U, &V);

            // 填充Y平面
            yuvBuffer[y_index++] = Y;

            // 每2x2块填充UV平面
            if (y % 2 == 0 && x % 2 == 0) {
                yuvBuffer[uv_index++] = V;
                yuvBuffer[uv_index++] = U;
            }
        }
    }
    
    // printf("Conversion complete!\n");
}

int read_bmp_rgb(const char *filename, uint8_t *rgbBuffer, RGBQuad palette[256])
{
    FILE *bmpFile = fopen(filename, "rb");
    if (!bmpFile) {
        perror("Error opening BMP file");
        return -1;
    }

    // 读取BMP文件头
    BMPFileHeader fileHeader;
    int ret = fread(&fileHeader, sizeof(BMPFileHeader), 1, bmpFile);
    if(0 > ret)
    {
        perror("fread fileHeader failed!\n");
        goto end;
    }

    // 读取BMP信息头
    BMPInfoHeader infoHeader;
    ret = fread(&infoHeader, sizeof(BMPInfoHeader), 1, bmpFile);
    if(0 > ret)
    {
        perror("fread infoHeader failed!\n");
        goto end;
    }

    // 检查图像位深度是否为8位
    if (infoHeader.biBitCount != 8) {
        printf("Error: Only 8-bit BMP files are supported.\n");
        goto end;
    }

    int width = infoHeader.biWidth;
    int height = infoHeader.biHeight;

    // 读取调色板（256个颜色）
    // RGBQuad palette[256];
    ret = fread(palette, sizeof(RGBQuad), 256, bmpFile);
    if(0 > ret)
    {
        perror("fread palette failed!\n");
        goto end;
    }

    // 读取像素数据
    // uint8_t *bmpData = (uint8_t *)malloc(width * height);
    fseek(bmpFile, fileHeader.bfOffBits, SEEK_SET);
    ret = fread(rgbBuffer, sizeof(uint8_t), width * height, bmpFile);
    if(0 > ret)
    {
        perror("fread rgbBuffer failed!\n");
        goto end;
    }

    fclose(bmpFile);

    return 0;
end:
    fclose(bmpFile);
    return -1;
}

#if 0
int yuv_to_bgrPacket_frame(VIDEO_FRAME_INFO_S *FrameInfo, unsigned char *dst)
{
    HI_S32 s32Ret;
    HI_U32 u32DstBlkSize;
    IVE_CSC_CTRL_S stCscCtrl;
    HI_BOOL bInstant = HI_TRUE;
    HI_BOOL bFinish;
    IVE_HANDLE IveHandle;

    g_sys_conf.stSrc_yvu420_packet.enType = IVE_IMAGE_TYPE_YUV420SP;
    g_sys_conf.stDst_bgr_packet.enType = IVE_IMAGE_TYPE_U8C3_PACKAGE;
    stCscCtrl.enMode = IVE_CSC_MODE_PIC_BT709_YUV2RGB;

    u32DstBlkSize = FrameInfo->stVFrame.u32Stride[0] * FrameInfo->stVFrame.u32Height * 3;

    g_sys_conf.stDst_bgr_packet.au32Stride[0] = FrameInfo->stVFrame.u32Stride[0];
    g_sys_conf.stDst_bgr_packet.u32Width = FrameInfo->stVFrame.u32Width;
    g_sys_conf.stDst_bgr_packet.u32Height = FrameInfo->stVFrame.u32Height;

    g_sys_conf.stSrc_yvu420_packet.au64PhyAddr[0] = FrameInfo->stVFrame.u64PhyAddr[0];
    g_sys_conf.stSrc_yvu420_packet.au64PhyAddr[1] = FrameInfo->stVFrame.u64PhyAddr[1];
    g_sys_conf.stSrc_yvu420_packet.au64PhyAddr[2] = FrameInfo->stVFrame.u64PhyAddr[2];

    g_sys_conf.stSrc_yvu420_packet.au64VirAddr[0] = (HI_U64) HI_MPI_SYS_Mmap(FrameInfo->stVFrame.u64PhyAddr[0],
                                                                             u32DstBlkSize / 2);

    g_sys_conf.stSrc_yvu420_packet.au64VirAddr[1] = g_sys_conf.stSrc_yvu420_packet.au64VirAddr[0] + FrameInfo->stVFrame.u32Stride[0] * FrameInfo->stVFrame.u32Height;
    g_sys_conf.stSrc_yvu420_packet.au64VirAddr[2] = g_sys_conf.stSrc_yvu420_packet.au64VirAddr[1] + (HI_U64) 1;

    g_sys_conf.stSrc_yvu420_packet.au32Stride[1] = FrameInfo->stVFrame.u32Stride[0];
    g_sys_conf.stSrc_yvu420_packet.au32Stride[0] = FrameInfo->stVFrame.u32Stride[0];
    g_sys_conf.stSrc_yvu420_packet.au32Stride[2] = 0;

    g_sys_conf.stSrc_yvu420_packet.u32Width = FrameInfo->stVFrame.u32Width;
    g_sys_conf.stSrc_yvu420_packet.u32Height = FrameInfo->stVFrame.u32Height;

    s32Ret = HI_MPI_IVE_CSC(&IveHandle, &g_sys_conf.stSrc_yvu420_packet, &g_sys_conf.stDst_bgr_packet, &stCscCtrl, bInstant);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_CSC failed with error code %#x\n", s32Ret);
    }

    s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_Query failed with error code %#x\n", s32Ret);
    }

    HI_MPI_SYS_MmzFlushCache(g_sys_conf.stDst_bgr_packet.au64PhyAddr[0],(void **) g_sys_conf.stDst_bgr_packet.au64VirAddr[0], u32DstBlkSize);

    memcpy((void *) (dst), (void *) g_sys_conf.stDst_bgr_packet.au64VirAddr[0], u32DstBlkSize);
    HI_MPI_SYS_Munmap((HI_VOID *) g_sys_conf.stSrc_yvu420_packet.au64VirAddr[0], u32DstBlkSize / 2);

    return HI_SUCCESS;
}

static HI_VOID *VENC_WebpStreamProc(HI_VOID *pArgs)
{
    dzlog_info("tid = %ld", (long int) syscall(224));
    HI_S32 s32Ret;
    VIDEO_FRAME_INFO_S stBaseFrmInfo;
    VIDEO_FRAME_INFO_S stExtFrmInfo;
    HI_S32 s32MilliSec = 20000;
    HI_S32 s32VpssGrp = 0;
    HI_S32 as32VpssChn[] = {VPSS_CHN0, VPSS_CHN1};
    g_sys_conf.webp_rgb_type_flag = 1;
    int number = 0;
    unsigned char *bgr_packet = (unsigned char *) malloc(1920 * 1080 * 3);

    int u32DstBlkSize = 1920 * 1080 * 3;
    s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&g_sys_conf.stDst_bgr_packet.au64PhyAddr[0],
                                        (void **) &g_sys_conf.stDst_bgr_packet.au64VirAddr[0],
                                        "user-dst2_ai_buffer", HI_NULL, u32DstBlkSize);

    while (g_sys_conf.APPRUN){

        s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo, s32MilliSec);
        if (HI_SUCCESS != s32Ret){
            dzlog_info("HI_MPI_VPSS_GetChnFrame false 1");
            usleep(10);
            continue;
        }

        s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo, s32MilliSec);
        if (HI_SUCCESS != s32Ret){
            dzlog_info("HI_MPI_VPSS_GetChnFrame false 0");
            goto EXT_RELEASE;
            usleep(10);
            continue;
        }

        number++;
        if (getQueueLen(0) == 0){
           	yuv_to_bgrPacket_frame(&stExtFrmInfo, bgr_packet);
            WriteQueue(bgr_packet, 1280 * 720 * 3, 0);	
        }

        if (getQueueLen(1) == 0){
           	yuv_to_bgrPacket_frame(&stBaseFrmInfo, bgr_packet);
            WriteQueue(bgr_packet, 1920 * 1080 * 3, 1);
        }

        BASE_RELEASE:
        s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo);
        if (HI_SUCCESS != s32Ret){
            SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",s32Ret, s32VpssGrp, as32VpssChn[0]);
        }

        EXT_RELEASE:
        s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo);
        if (HI_SUCCESS != s32Ret){
            //SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",s32Ret,s32VpssGrp,as32VpssChn[1]);
        }

    }
    HI_MPI_SYS_MmzFree(g_sys_conf.stDst_bgr_packet.au64PhyAddr[0],
                       (HI_VOID *) g_sys_conf.stDst_bgr_packet.au64VirAddr[0]);
    free(bgr_packet);
    bgr_packet = NULL;

    return HI_NULL;
}

int main() {
    unsigned char rgb_data[WIDTH * HEIGHT * 3];
    unsigned char yuv_data[WIDTH * HEIGHT * 3 / 2]; // YUV 420 格式的大小是 1.5 倍的像素数

    init_ive();  // 初始化 IVE

    // 从 BMP 中读取 RGB 数据
    if (read_bmp_rgb("input.bmp", rgb_data) == 0) {
        printf("RGB data loaded successfully.\n");
    }

    // 转换 RGB 到 YUV
    if (convert_rgb_to_yuv(rgb_data, yuv_data) == 0) {
        printf("RGB to YUV conversion completed.\n");
    }

    // 释放 IVE 资源
    HI_MPI_IVE_Exit();

    return 0;
}

#endif

#define VOT_VPSS_EN (1)
#define VOT_VO_EN   (0)
#define VOT_VENC_EN (1)

#define VPSS_WIDTH  (720)  //(1920)
#define VPSS_HEIGHT (576)  //(1080)
// #define SEND_DATA_BY_USER
#define MAX_THREADS (10)

HI_VOID *vi_capture_thread(HI_VOID *arg) {
    ThreadParams *params = (ThreadParams *)arg;
    VI_CHN viChn = params->ViChn;
    VI_CHN viPipe = params->ViPipe;
    const char *outputFile = params->outputFile;

    FILE *file = fopen(outputFile, "w");
    if (!file) {
        perror("Failed to open output file");
        return NULL;
    }

    fd_set fds;
    struct timeval tv, tv_get;
    VIDEO_FRAME_INFO_S stFrame, dstFrame;
    // VIDEO_FRAME_INFO_S *stFrame = malloc(sizeof(VIDEO_FRAME_INFO_S));
    stFrame.enModId = MOD_ID_VI;
    stFrame.u32PoolId = 1;
    stFrame.stVFrame.enColorGamut =     COLOR_GAMUT_BT709;
    stFrame.stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    stFrame.stVFrame.enDynamicRange =   DYNAMIC_RANGE_SDR8;
    stFrame.stVFrame.enCompressMode =   COMPRESS_MODE_NONE;
    stFrame.stVFrame.enField =          VIDEO_FIELD_FRAME;
    stFrame.stVFrame.enVideoFormat =    VIDEO_FORMAT_LINEAR;
    stFrame.stVFrame.s16OffsetBottom =  0;
    stFrame.stVFrame.s16OffsetLeft =    0;
    stFrame.stVFrame.s16OffsetRight =   0;
    stFrame.stVFrame.s16OffsetTop =     0;
    stFrame.stVFrame.u32Width   =       640;
    stFrame.stVFrame.u32Height  =       512;
    stFrame.stVFrame.u64PTS     =       25 * 40;

    HI_U64 u64PhyAddrYuv;
	HI_VOID *ppVirAddrYuv;
	HI_U64 phyYaddr;
	HI_U64* virYaddr;
	FILE *fb = HI_NULL; 
	HI_BOOL isOneFrame = HI_FALSE;
	HI_U64 pu64CurPTS;

    int ret;
    int cnt = 0;
    int viFd = HI_MPI_VI_GetChnFd(viPipe, viChn);
    int index = 0;
    
    if (viFd < 0) {
        fprintf(stderr, "Failed to get VI channel FD\n");
        fclose(file);
        return NULL;
    }

    int yuv_size = 640 * HEIGHT * 3 / 2;
    int y_vir_size = 640 * HEIGHT ;
    int u_vir_size = 640 * HEIGHT  / 2;
    uint8_t *nv12_data = (uint8_t *)malloc(yuv_size);
#ifndef SEND_RAW_DATA

    // 1.开辟内存地址，id+addr
    VB_BLK handleY  = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, yuv_size, NULL);
    if( handleY == VB_INVALID_HANDLE)
    {
        usleep(10);
        printf("HI_MPI_VB_GetBlock for Block failed\n");
    }
    VB_POOL poolID =  HI_MPI_VB_Handle2PoolId(handleY);
    //printf("pool id %d\n", poolID);

    phyYaddr = HI_MPI_VB_Handle2PhysAddr(handleY);
    if( phyYaddr == 0)
    {
        printf("HI_MPI_VB_Handle2PhysAddr for handleY failed\n");
        goto end;
    }

    int thread_count = 0;
    int y_size = 640 * HEIGHT * 2;
    int uv_size = 640 * 512 * 2;
    int uv_raw_size = 640 * HEIGHT * 2;
    // SendZstdData_S thread_arg;
    pthread_t threads[MAX_THREADS];
    int thread_ids[MAX_THREADS];
    pthread_mutex_t zstd_mutex;
    pthread_mutex_init(&zstd_mutex, NULL);

    HI_U8* pu8VirAddr   = (HI_U8*)malloc(uv_raw_size);
    SendZstdData_S* thread_arg  = (SendZstdData_S*)malloc(sizeof(SendZstdData_S));
    threadpool thpool = thpool_init(1);
#endif
    while (1) {
        FD_ZERO(&fds);
        FD_SET(viFd, &fds);
        tv.tv_sec = 4;
        tv.tv_usec = 0;

        ret = select(viFd + 1, &fds, NULL, NULL, &tv);
        if (ret < 0) {
            perror("select failed");
            break;
        } else if (ret == 0) {
            fprintf(stderr, "select timeout\n");
            continue;
        }

        if (FD_ISSET(viFd, &fds)) 
        {

    #ifdef SEND_BMP_TO_VI_DATA
        ret = HI_MPI_VI_GetChnFrame(viPipe, viChn, &stFrame, 1000);
        if (ret != HI_SUCCESS) {
            fprintf(stderr, "Failed to get frame from VI channel\n");
            continue;
        }

        #ifdef SEND_BMP8_2_NV12
            //1.get on frame rgb img from file
            //2.use HI_MPI_IVE_CSC to rgb2yuv
            //3.send yuv to venc to rtsp
            uint8_t bmp_data[WIDTH * HEIGHT * 3];
            RGBQuad palette[256] = {0};
            int8_t filename[128] = {0};
            uint64_t cur_time =  get_current_timestamp_ms();

            sprintf(filename, "/nfs/start/img_%d_numbered.bmp", index++%36);
            // info("filenmae=%s\n",filename);
            int ret = read_bmp_rgb(filename, bmp_data, palette);
            if(0 != ret)
            {
                perror("Error read_bmp_rgb ");
                sleep(1);
                continue;
            }

            rgb_to_nv12(bmp_data, palette, nv12_data, RAW_WIDTH, RAW_HEIGHT);
        
            if(index == 1){
                // 写入NV12文件
                FILE *nv12File = fopen("/nfs/output_1.yuv", "wb");
                if (!nv12File) {
                    perror("Error opening NV12 output file");
                    sleep(1);
                    continue;
                }

                fwrite(nv12_data, 1, yuv_size, nv12File);
                fclose(nv12File);
            }
        #else
            uint8_t bmp_data[WIDTH * HEIGHT * 3];
            int8_t filename[128] = {0};
            sprintf(filename, "/nfs/start/img_%d.bmp", index++%36);

            convert_rgb_to_yuv_self(filename, bmp_data, nv12_data, RAW_WIDTH, RAW_HEIGHT);

        #endif
        // memset(nv12_data, 0x80, yuv_size);
        uint64_t curr_time = get_current_timestamp_ms();
        // info("cost time:%llu ms\n", curr_time - cur_time);
        // info("stFrame.stVFrame.u64PhyAddr[0]=%p\n",stFrame.stVFrame.u64PhyAddr[0]);
        HI_U8*   pu8VirAddr = (HI_U8 *) HI_MPI_SYS_Mmap(stFrame.stVFrame.u64PhyAddr[0], yuv_size);//u64Size
        if (NULL == pu8VirAddr)
        {
            err("HI_MPI_SYS_Mmap fail !\n");
            // HI_MPI_VB_ReleaseBlock(VbBlk);
            continue;
        }

        memcpy(pu8VirAddr, nv12_data, yuv_size);

        if(index < 37){
            // 写入NV12文件
            int8_t yuv_filename[128] = {0};
            sprintf(yuv_filename, "/nfs/nv12_no_num_%d.yuv", index);
            FILE *nv12File = fopen(yuv_filename, "wb");
            if (!nv12File) {
                perror("Error opening NV12 output file");
                sleep(1);
                continue;
            }

            fwrite(nv12_data, 1, yuv_size, nv12File);
            fclose(nv12File);
        }
    
        ret = HI_MPI_VENC_SendFrame( 1, &stFrame, -1);
        if (HI_SUCCESS != ret)
        {
            err("HI_MPI_VENC_SendFrame failed, s32Ret = [0x%x].\n", ret);
        }else if(index == 1){
            info("HI_MPI_VENC_SendFrame ok, s32Ret = [0x%x].\n", ret);
        }
        curr_time = get_current_timestamp_ms();
        // info("cost2 time:%llu ms\n", curr_time - cur_time);

        HI_MPI_SYS_Munmap(pu8VirAddr, yuv_size);//u64Size
        pu8VirAddr = NULL;
        HI_MPI_VI_ReleaseChnFrame(viPipe, viChn, &stFrame);

        // usleep(10000);
    #else       
            uint64_t curr_time = get_current_timestamp_ms();
            // info("cost time:%llu ms\n", curr_time - cur_time);

            ret = HI_MPI_VI_GetChnFrame(viPipe, viChn, &stFrame, 1000);
            if (ret != HI_SUCCESS) {
                fprintf(stderr, "Failed to get frame from VI channel\n");
                continue;
            }
            if(0 == cnt)
                printf("pts=%llu\n",stFrame.stVFrame.u64PTS);

            
        #ifndef SEND_DATA_BY_USER
            
            // HI_U8*   pu8VirAddr = (HI_U8 *) HI_MPI_SYS_Mmap(stFrame.stVFrame.u64PhyAddr[0], yuv_size);//u64Size
            // if (NULL == pu8VirAddr)
            // {
            //     err("HI_MPI_SYS_Mmap fail !\n");
            //     // HI_MPI_VB_ReleaseBlock(VbBlk);
            //     continue;
            // }
            
            HI_U8  * pu8VirAddr_y = NULL;
            HI_U8  * pu8VirAddr_uv = NULL;

            VIDEO_FRAME_S *pVBuf = (VIDEO_FRAME_S *)&stFrame.stVFrame;
            if(pVBuf->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422)
            {
                y_size = (pVBuf->u32Width) * (pVBuf->u32Height);
                uv_size = (pVBuf->u32Width) * (pVBuf->u32Height);
            }
            else if(pVBuf->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420)
            {
                y_size = (pVBuf->u32Width) * (pVBuf->u32Height);
                uv_size = (pVBuf->u32Width) * (pVBuf->u32Height) / 2;
            }

            if(0 == cnt)
                info("y_size=%u,uv_size=%d,yuv_size=%d\n",y_size, uv_size, yuv_size);

            pu8VirAddr_y = (HI_U8 *) HI_MPI_SYS_Mmap(pVBuf->u64PhyAddr[0], y_size + uv_size);
            pu8VirAddr_uv = (HI_U8 *) HI_MPI_SYS_Mmap(pVBuf->u64PhyAddr[1], uv_size);

            // FILE *pfd_y = fopen("/nfs/test_y.yuv", "wb");
            // FILE *pfd_uv = fopen("/nfs/test_uv.yuv", "wb");

            // fwrite(pu8VirAddr_y,  y_size ,1, pfd_y);
            // fwrite(pu8VirAddr_uv,  uv_size ,1, pfd_uv);

            // fclose(pfd_y);
            // fclose(pfd_uv);

            // memcpy(pu8VirAddr, pu8VirAddr_y, y_size);
            // SendZstdData_S* thread_arg  = (SendZstdData_S*)malloc(sizeof(SendZstdData_S));
            memcpy(pu8VirAddr, pu8VirAddr_uv, uv_size);
            // info("y_size=%u,uv_size=%d,yuv_size=%d\n",y_size, uv_size, yuv_size);

            thread_arg->pu8VirAddr_uv = pu8VirAddr;
            thread_arg->thread_count  = thread_count;
            thread_arg->uv_size       = uv_size;
            thread_arg->mutex         = zstd_mutex;
            // thread_arg->queue         = queue;
            // thread_arg->sock          = sock;
            thread_ids[thread_count]  = thread_count;

            // send_ztsd_data_to_user(thread_arg);
            thpool_add_work(thpool, send_ztsd_data_to_user, (HI_VOID*)thread_arg);

            thread_count++;

            #ifdef DEBUG
                stFrame.stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
                stFrame.stVFrame.u32Height = 512;
                stFrame.stVFrame.u32Width = 640;
                stFrame.stVFrame.u32Stride[0] = 640;
                stFrame.stVFrame.u32Stride[1] = 640;
                stFrame.stVFrame.u32Stride[2] = 640;


                ret = HI_MPI_VENC_SendFrame( 1, &stFrame, -1);
                if (HI_SUCCESS != ret)
                {
                    err("HI_MPI_VENC_SendFrame failed, s32Ret = [0x%x].\n", ret);
                }else if(index == 1){
                    info("HI_MPI_VENC_SendFrame ok, s32Ret = [0x%x].\n", ret);
                }
            #endif
           

        #else
            if(cnt < 3)
                VIO_VIchn_frame_Save(&stFrame, cnt);

            cnt++;
            // ret = get_vichn_raw_date_sendto_venc( &stFrame, 1, file); 
            // if (ret != HI_SUCCESS) {
            //     err("HI_MPI_VENC_SendFrame failed:0x%x\n", ret);
            //     continue;
            // }
           
        #endif
            
    
       
        if(cnt < 4)
            info("handleY=%d, phyYaddr=%x\n", handleY, phyYaddr);

        virYaddr = (HI_U64*) HI_MPI_SYS_Mmap(phyYaddr, yuv_size);

        //2.映射后赋值,old_2_new
            if(!isOneFrame)
            {
                memset(&dstFrame.stVFrame, 0, sizeof(VIDEO_FRAME_S));
                dstFrame.enModId = HI_ID_VENC;
                dstFrame.u32PoolId = poolID;
                dstFrame.stVFrame.u64PhyAddr[0] = phyYaddr;
                dstFrame.stVFrame.u64PhyAddr[1] = dstFrame.stVFrame.u64PhyAddr[0] + y_vir_size;
                // dstFrame.stVFrame.u64PhyAddr[2] = dstFrame.stVFrame.u64PhyAddr[1] + u32YSize;

                dstFrame.stVFrame.u64VirAddr[0] = (HI_U64 *)virYaddr;
                dstFrame.stVFrame.u64VirAddr[1] = (HI_U64 *)dstFrame.stVFrame.u64VirAddr[0] + y_vir_size;
                //stFrame.stVFrame.u64VirAddr[2] = (HI_U8 *) stFrame.stVFrame.u64VirAddr[1] + u32YSize;

                dstFrame.stVFrame.u32Width	   = 640;
                dstFrame.stVFrame.u32Height    = 512;
                dstFrame.stVFrame.u32Stride[0] = 640;
                dstFrame.stVFrame.u32Stride[1] = 640;
                //stFrame.stVFrame.u32Stride[2] = 3840;
                // HI_MPI_SYS_GetCurPTS(&pu64CurPTS);
                dstFrame.stVFrame.u64PTS	 = stFrame.stVFrame.u64PTS;
                dstFrame.stVFrame.u32TimeRef = stFrame.stVFrame.u32TimeRef;//timeref need n*2 but you can't get the second frame
                dstFrame.stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
                dstFrame.stVFrame.enField = VIDEO_FIELD_FRAME;
                dstFrame.stVFrame.enCompressMode = COMPRESS_MODE_NONE;
                dstFrame.stVFrame.enVideoFormat  = VIDEO_FORMAT_LINEAR;
                dstFrame.stVFrame.enDynamicRange = DYNAMIC_RANGE_SDR8;
            }
            else
            {
                dstFrame.stVFrame.u64PTS	 = stFrame.stVFrame.u64PTS;
                dstFrame.stVFrame.u32TimeRef = stFrame.stVFrame.u32TimeRef;//timeref need n*2 but you can't get the second frame
            }

            memcpy(virYaddr, pu8VirAddr_y, yuv_size);
            if(4 > cnt)
                warn("pVBuf->u64PhyAddr[0]=%x,pu8VirAddr_y=%x, virYaddr=%x,phyYaddr=%x, dstFrame.stVFrame.u64PhyAddr[0]=%x, dstFrame.stVFrame.u64VirAddr[0]=%x\n", pVBuf->u64PhyAddr[0], pu8VirAddr_y, virYaddr, phyYaddr, dstFrame.stVFrame.u64PhyAddr[0], dstFrame.stVFrame.u64VirAddr[0]);

    #ifdef SEND_USR_DATA_TO_VENC
            ret = HI_MPI_VENC_SendFrame(1, &dstFrame, -1);
            if (HI_SUCCESS != ret)
            {
                err("HI_MPI_VENC_SendFrame failed, s32Ret = [0x%x].\n", ret);
            }
            // else{
            //     info("HI_MPI_VENC_SendFrame ok, s32Ret = [0x%x].\n", ret);
            // }
    #else
            ret = HI_MPI_VPSS_SendFrame(0 , 0, &dstFrame, -1);
            if (HI_SUCCESS != ret)
            {
                err("HI_MPI_VPSS_SendFrame failed, s32Ret = [0x%x].\n", ret);
            }
            // else{
            //     info("HI_MPI_VPSS_SendFrame ok, s32Ret = [0x%x].\n", ret);
            // }
    #endif
            cnt++;
            if(cnt < 4)
            {
                // VIO_VIchn_frame_Save(&dstFrame, cnt);
                uint64_t cur_time = get_current_timestamp_ms();
                
                info("==================cost time:%llu ms\n", cur_time - curr_time);
            }
                
            HI_MPI_SYS_Munmap(virYaddr, yuv_size);
            virYaddr = NULL;

            HI_MPI_SYS_Munmap(pu8VirAddr_y, y_size + uv_size);//u64Size
            pu8VirAddr_y = NULL;

            HI_MPI_SYS_Munmap(pu8VirAddr_uv, uv_size);//u64Size
            pu8VirAddr_uv = NULL;
            
            HI_MPI_VI_ReleaseChnFrame(viPipe, viChn, &stFrame);;
    #endif
        }
    }

end:
    free(nv12_data);
    fclose(file);
    // free(pu8VirAddr);
    // free(thread_arg);
    // HI_MPI_VB_ReleaseBlock(handleY);
    // thpool_destroy(thpool);
    // HI_MPI_SYS_MmzFree(u64PhyAddrYuv, ppVirAddrYuv);
    return NULL;
}


#if 0
HI_S32 SAMPLE_VIO_ViOnlineVpssOnlineRoute(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = VI_PIPE_PIXFMT;//PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VENC_CHN           VencChn[1]  = {0};
    PAYLOAD_TYPE_E     enType      = PT_H265;
    SAMPLE_RC_E        enRcMode    = SAMPLE_RC_CBR;
    HI_U32             u32Profile  = 0;
    HI_BOOL            bRcnRefShareBuf = HI_TRUE;
    VENC_GOP_ATTR_S    stGopAttr;
    
    HI_S32             s32MilliSec = 4000;
    HI_U32             u32CapCnt = 0;
    HI_S32             s32DumpCnt = 0;
    VI_CMP_PARAM_S     stCmpPara;
    VIDEO_FRAME_INFO_S astFrame[MAX_FRM_CNT];

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = VI_PIPE_PIXFMT;//enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;//1

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = (stSize.u32Width * stSize.u32Height * 3);//u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 3;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = (stSize.u32Width * stSize.u32Height * 3);//u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 5;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    SAMPLE_PRT("[0920]: stSize.w/h = (%d, %d)-[%d, %d], u64BlkSize[0] = [%lld][%u], , u64BlkSize[1] = [%lld][%u] !\n", \
        stSize.u32Width, stSize.u32Height, IN_WIDTH, IN_HEIGHT, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize);

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = (stSize.u32Width-80);//stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = (stSize.u32Height-64);//stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 8;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    VPSS_CROP_INFO_S stVpssCropInfo;

    stVpssCropInfo.bEnable = HI_TRUE;
    stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
    stVpssCropInfo.stCropRect.s32X = 40;
    stVpssCropInfo.stCropRect.s32Y = 32;
    stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width-80;
    stVpssCropInfo.stCropRect.u32Height = stSize.u32Height-64;
    s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

#if 1


#else
        s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &astFrame[0], s32MilliSec);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
        }
        else {
            SAMPLE_PRT("HI_MPI_VI_GetChnFrame() done. s32Ret: [0x%x] !\n", s32Ret);
            VIO_VIchn_frame_Save(&astFrame[0]);
            s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe, ViChn, &astFrame[0]);
        }
    
        SAMPLE_DUMP_Proc();
        SAMPLE_COMM_VI_StartDumpRawThread(ViPipe, 50, "vot");
        SAMPLE_PRT("Start Dump Raw Thread().\n");
        sleep(5);
        SAMPLE_PRT("Dump Raw Thread() done.\n");
        SAMPLE_COMM_VI_StopDumpRawThread();
#endif





    PAUSE();


#if VOT_VPSS_EN
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
#endif

EXIT2:
#if VOT_VPSS_EN
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
#endif

EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

#endif


void SAMPLE_DUMP_INIT(HI_BOOL initFlag)
{
    VI_DEV            ViDev                = 0;
    VI_PIPE           ViPipe               = 0;
    static VI_PIPE           ViPipeId[4]          = {0};  /* save main pipe to [4] */
    HI_S32            s32Ret               = 0;
    HI_U32            i                    = 0;
    HI_U32            u32FrmCnt            = 1;
    HI_U32            u32RawDepth          = 2;
    HI_U32            u32ByteAlign         = 1;
    static HI_U32            u32PipeNum           = 0;   /* LineMode -> 1, WDRMode -> 2~3 */
    HI_U32            u32RatioShow         = 1;
    COMPRESS_MODE_E   enCompressMode       = COMPRESS_MODE_NONE;
    VI_DUMP_ATTR_S    stRawDumpAttr;
    VI_DUMP_ATTR_S    stDumpAttr;
    VI_DEV_ATTR_S     stDevAttr;
    static VI_PIPE_ATTR_S    astBackUpPipeAttr[4];
    VI_PIPE_ATTR_S    stPipeAttr;

    //enCompressMode = COMPRESS_MODE_NONE; /* non_compress_mode */
    u32FrmCnt      = 1;  /* frame number is 1 */
    u32ByteAlign   = 1;  /* convert to Byte align */
    u32RatioShow   = 0;  /* ratio not shown */

    if (initFlag)
    {
        s32Ret = HI_MPI_VI_GetDevAttr(ViDev, &stDevAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Get dev %d attr failed!\n", ViDev);
            goto EXIT;
        }

        s32Ret = VIO_getDumpPipe(ViDev, stDevAttr.stWDRAttr.enWDRMode, &u32PipeNum, ViPipeId);

        if (HI_SUCCESS != s32Ret)
        {
            printf("getDumpPipe failed 0x%x!\n", s32Ret);
            goto EXIT;
        }

        printf("Setting Parameter ==> enWDRMode(%d), u32PipeNum(%d), ViPipeId = [%d][%d][%d][%d].\n", \
            stDevAttr.stWDRAttr.enWDRMode, u32PipeNum, ViPipeId[0], ViPipeId[1], ViPipeId[2], ViPipeId[3]);

        //return s32Ret;

        for (i = 0; i < u32PipeNum; i++)
        {
            s32Ret = HI_MPI_VI_GetPipeDumpAttr(ViPipeId[i], &stRawDumpAttr);
            printf("Get Pipe %d dump attr[0x%x], stRawDumpAttr = [%d](%d){%d}\n", ViPipeId[i], s32Ret, \
                stRawDumpAttr.bEnable, stRawDumpAttr.u32Depth, stRawDumpAttr.enDumpType);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Get Pipe %d dump attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }

            memcpy(&stDumpAttr, &stRawDumpAttr, sizeof(VI_DUMP_ATTR_S));
            stDumpAttr.bEnable                       = HI_TRUE;
            stDumpAttr.u32Depth                      = u32RawDepth;
            stDumpAttr.enDumpType                    = VI_DUMP_TYPE_YUV;
            s32Ret = HI_MPI_VI_SetPipeDumpAttr(ViPipeId[i], &stDumpAttr);
            printf("Set Pipe %d dump attr[0x%x], stDumpAttr = [%d](%d){%d}\n", ViPipeId[i], s32Ret, \
                stDumpAttr.bEnable, stDumpAttr.u32Depth, stDumpAttr.enDumpType);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Set Pipe %d dump attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }
            /*
            s32Ret = HI_MPI_VI_GetPipeAttr(ViPipeId[i], &astBackUpPipeAttr[i]);
            printf("Get Pipe %d attr[0x%x], astBackUpPipeAttr.enCompressMode = [%d].\n", ViPipeId[i], s32Ret, \
                astBackUpPipeAttr[i].enCompressMode);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Get Pipe %d attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }

            memcpy(&stPipeAttr, &astBackUpPipeAttr[i], sizeof(VI_PIPE_ATTR_S));
            stPipeAttr.enCompressMode = enCompressMode;
            s32Ret = HI_MPI_VI_SetPipeAttr(ViPipeId[i], &stPipeAttr);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Set Pipe %d attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }//*/
        }

        printf("--> u32PipeNum=%d\n", u32PipeNum);
    }
    else
    {
        for (i = 0; i < u32PipeNum; i++)
        {
            s32Ret = HI_MPI_VI_SetPipeAttr(ViPipeId[i], &astBackUpPipeAttr[i]);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Set Pipe %d attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }

            s32Ret = HI_MPI_VI_SetPipeDumpAttr(ViPipeId[i], &stRawDumpAttr);

            if (HI_SUCCESS != s32Ret)
            {
                printf("Set Pipe %d dump attr failed!\n", ViPipeId[i]);
                goto EXIT;
            }
        }
    }

EXIT:
    return s32Ret;
}


void VIO_SAVE_FILE(VI_PIPE ViPipe)
{
    int                 i, j;
    HI_S32              s32Ret;
    HI_S32              s32MilliSec = 4000;
    HI_U32              u32CapCnt = 0;
    HI_S32              s32DumpCnt = 0;
    VI_CMP_PARAM_S      stCmpPara;
    VIDEO_FRAME_INFO_S  astFrame[MAX_FRM_CNT];
    ISP_MESH_SHADING_TABLE_S  stIspMLSCTable;
    FILE       *pfile = NULL;
    HI_CHAR     name[128] = {0};
    HI_U32      u32Width;
    HI_U32      u32Height;
    HI_U32      u32BitWidth;

    /* get VI frame */
    for (i = 0; i < MAX_FRM_CNT; ++i)
    {
        memset_s(&astFrame[i], sizeof(VIDEO_FRAME_INFO_S), 0, sizeof(VIDEO_FRAME_INFO_S));
        s32Ret = HI_MPI_VI_GetPipeFrame(ViPipe, &astFrame[i], s32MilliSec);
        if (HI_SUCCESS != s32Ret)
        {
            printf("get vi Pipe %d frame err, s32Ret = [0x%x].\n", ViPipe, s32Ret);
            printf("only get %d frame\n", i);
            break;
        }

        printf("get vi Pipe %d frame num %d ok\n", ViPipe, i);
    }

    u32CapCnt = i;

    if (0 == u32CapCnt)
    {
        printf("get vi Pipe %d frame num [%d], u32CapCnt = [%d].\n", ViPipe, i, u32CapCnt);
        return HI_FAILURE;
    }

    /* dump file */
    u32Width    = astFrame[0].stVFrame.u32Width;
    u32Height   = astFrame[0].stVFrame.u32Height;
    u32BitWidth = SAMPLE_COMM_VI_PixelFormat2BitWidth(astFrame[0].stVFrame.enPixelFormat);

    snprintf(name, sizeof(name), "/mnt/dump_pipe%d_w%d_h%d_%dbits_%s_25.raw", ViPipe, u32Width,
        u32Height, u32BitWidth, SAMPLE_COMM_VI_CompressMode2String(astFrame[0].stVFrame.enCompressMode));
    pfile = fopen(name, "ab");
    if (NULL == pfile)
    {
        SAMPLE_PRT("open file %s fail !\n", name);
        return HI_NULL;
    }

    for (j = 0; j < u32CapCnt; j++)
    {
        /* save VI frame to file */
        //VIO_Frame_svFile(ViPipe, &astFrame[j].stVFrame, u32MeshScale, u32ByteAlign, &stIspMLSCTable);

        s32Ret = SAMPLE_COMM_VI_SaveRaw(&astFrame[0].stVFrame, u32BitWidth, pfile);

        /* release frame after using */
        HI_MPI_VI_ReleasePipeFrame(ViPipe, &astFrame[j]);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SaveRaw failed with %#x!\n", s32Ret);
            goto end;
        }

        s32DumpCnt++;
    }

end:
    if (pfile) {
        fclose(pfile);
        pfile = HI_NULL;
    }
    fprintf(stderr, "s32DumpCnt = [%d] ------Done!\n", s32DumpCnt);

    return HI_SUCCESS;
}

void save_frame(const VIDEO_FRAME_S *pstVideoFrame, const char *filename) {
    FILE *pFile = fopen(filename, "wb");
    if (!pFile) {
        perror("Failed to open file");
        return;
    }

    for (HI_U32 i = 0; i < pstVideoFrame->u32Height; i++) {
        fwrite((void *)pstVideoFrame->u64VirAddr[0] + i * pstVideoFrame->u32Stride[0], 1, pstVideoFrame->u32Width, pFile);
    }

    if (pstVideoFrame->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
        for (HI_U32 i = 0; i < pstVideoFrame->u32Height / 2; i++) {
            fwrite((void *)pstVideoFrame->u64VirAddr[1] + i * pstVideoFrame->u32Stride[1], 1, pstVideoFrame->u32Width, pFile);
        }
    }
    else if(pstVideoFrame->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
        for (HI_U32 i = 0; i < pstVideoFrame->u32Height; i++) {
            fwrite((void *)pstVideoFrame->u64VirAddr[1] + i * pstVideoFrame->u32Stride[1], 1, pstVideoFrame->u32Width, pFile);
        }
    }

    fclose(pFile);
}

static HI_S32 InitVbPool(HI_U32 u32Width, HI_U32 u32Height, PIXEL_FORMAT_E enPixelFormat, VB_BLK *pstBlk, VIDEO_FRAME_INFO_S *pstFrame)
{
    HI_S32 s32Ret;
    VB_POOL_CONFIG_S stVbPoolCfg;
    VB_POOL hVbPool = VB_INVALID_POOLID;

    memset(&stVbPoolCfg, 0, sizeof(stVbPoolCfg));
    stVbPoolCfg.u64BlkSize = COMMON_GetPicBufferSize(u32Width, u32Height, enPixelFormat, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbPoolCfg.u32BlkCnt = 1;
    stVbPoolCfg.enRemapMode = VB_REMAP_MODE_NONE;

    hVbPool = HI_MPI_VB_CreatePool(&stVbPoolCfg);
    if (hVbPool == VB_INVALID_POOLID)
    {
        printf("HI_MPI_VB_CreatePool failed!\n");
        return HI_FAILURE;
    }

    *pstBlk = HI_MPI_VB_GetBlock(hVbPool, stVbPoolCfg.u64BlkSize, NULL);
    if (*pstBlk == VB_INVALID_HANDLE)
    {
        printf("HI_MPI_VB_GetBlock failed!\n");
        return HI_FAILURE;
    }

    pstFrame->u32PoolId = HI_MPI_VB_Handle2PoolId(*pstBlk);
    if (pstFrame->u32PoolId == VB_INVALID_POOLID)
    {
        printf("HI_MPI_VB_Handle2PoolId failed!\n");
        return HI_FAILURE;
    }

    pstFrame->stVFrame.u64PhyAddr[0] = HI_MPI_VB_Handle2PhysAddr(*pstBlk);
    pstFrame->stVFrame.u64PhyAddr[1] = pstFrame->stVFrame.u64PhyAddr[0] + u32Width * u32Height;

    pstFrame->stVFrame.u64VirAddr[0] = HI_MPI_SYS_Mmap(pstFrame->stVFrame.u64PhyAddr[0], u32Width * u32Height * 2);
    if (pstFrame->stVFrame.u64VirAddr[0] == NULL)
    {
        printf("HI_MPI_SYS_Mmap failed!\n");
        return HI_FAILURE;
    }

    pstFrame->stVFrame.u64VirAddr[1] = pstFrame->stVFrame.u64VirAddr[0] + u32Width * u32Height;

    pstFrame->stVFrame.u32Stride[0] = u32Width;
    pstFrame->stVFrame.u32Stride[1] = u32Width;

    pstFrame->stVFrame.u32Width = u32Width;
    pstFrame->stVFrame.u32Height = u32Height;
    pstFrame->stVFrame.enPixelFormat = enPixelFormat;
    pstFrame->stVFrame.enField = VIDEO_FIELD_FRAME;
    pstFrame->stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
    pstFrame->stVFrame.enCompressMode = COMPRESS_MODE_NONE;
    pstFrame->stVFrame.enDynamicRange = DYNAMIC_RANGE_SDR8;
    pstFrame->stVFrame.enColorGamut = COLOR_GAMUT_BT709;

    return HI_SUCCESS;
}

static void* YUV_SendThread(void* arg)
{
    HI_S32 s32Ret;
    VI_PIPE ViPipe = *(VI_PIPE*)arg;

    VI_PIPE_ATTR_S stPipeAttr;
    s32Ret = HI_MPI_VI_GetPipeAttr(ViPipe, &stPipeAttr);
    if (s32Ret != HI_SUCCESS)
    {
        printf("HI_MPI_VI_GetPipeAttr failed with error code: %#x\n", s32Ret);
        return NULL;
    }

    stPipeAttr.enPixFmt = PIXEL_FORMAT_YVU_SEMIPLANAR_422;
    stPipeAttr.u32MaxW = WIDTH;
    stPipeAttr.u32MaxH = HEIGHT;

    s32Ret = HI_MPI_VI_SetPipeAttr(ViPipe, &stPipeAttr);
    if (s32Ret != HI_SUCCESS)
    {
        printf("HI_MPI_VI_SetPipeAttr failed with error code: %#x\n", s32Ret);
        return NULL;
    }

    VI_PIPE_FRAME_SOURCE_E pipe_source = 100;
    s32Ret = HI_MPI_VI_GetPipeFrameSource(ViPipe, &pipe_source);
    if (s32Ret != HI_SUCCESS)
    {
        printf("HI_MPI_VI_GetPipeFrameSource failed with error code: %#x\n", s32Ret);
        return NULL;
    }
    printf("HI_MPI_VI_GetPipeFrameSource: %d\n", pipe_source);

    s32Ret = GK_API_VI_SetPipeFrameSource(ViPipe, VI_PIPE_FRAME_SOURCE_USER_BE);
    if (s32Ret != HI_SUCCESS)
    {
        printf("GK_API_VI_SetPipeFrameSource failed with error code: %#x\n", s32Ret);
        return NULL;
    }

    VB_BLK hVbBlk;
    VIDEO_FRAME_INFO_S stFrame;
    s32Ret = InitVbPool(WIDTH, HEIGHT, PIXEL_FORMAT_YVU_SEMIPLANAR_422, &hVbBlk, &stFrame);
    if (s32Ret != HI_SUCCESS)
    {
        printf("InitVbPool failed!\n");
        return NULL;
    }

    memset(stFrame.stVFrame.u64VirAddr[0], 0x90, WIDTH * HEIGHT);     // 填充Y分量
    memset(stFrame.stVFrame.u64VirAddr[1], 0x80, WIDTH * HEIGHT);     // 填充UV分量

    s32Ret = HI_MPI_VI_SendPipeYUV(ViPipe, &stFrame, 1000);
    if (s32Ret != HI_SUCCESS)
    {
        printf("HI_MPI_VI_SendPipeYUV failed with error code: %#x\n", s32Ret);
        HI_MPI_SYS_Munmap(stFrame.stVFrame.u64VirAddr[0], WIDTH * HEIGHT * 2);
        HI_MPI_VB_ReleaseBlock(hVbBlk);
        return NULL;
    }
    printf("YUV422 data sent successfully!\n");

    HI_MPI_SYS_Munmap(stFrame.stVFrame.u64VirAddr[0], WIDTH * HEIGHT * 2);
    HI_MPI_VB_ReleaseBlock(hVbBlk);

    return NULL;
}

static HI_S32 insert_usr_pic(SAMPLE_VI_CONFIG_S* pstViConfig)
{
    HI_S32              s32Ret = HI_SUCCESS;
    HI_S32              i, j;
    HI_S32              s32ViNum;
    SAMPLE_SNS_TYPE_E    enSnsType;
    SAMPLE_VI_INFO_S    *pstViInfo = HI_NULL;
    VI_USERPIC_ATTR_S *pstVFrameInfo;
    HI_U32 u32LStride = 0;
    HI_U32 u32CStride = 0;
    HI_U32 u32LumaSize = 0;
    HI_U32 u32ChrmSize = 0;
    HI_U32 u32Size = 0;
    VB_BLK VbBlk;
    HI_U64 u64PhyAddr;
    HI_VOID *ppVirAddr;
    HI_U8  *p, *puv, *pu, *pv;
    FILE *fpic = NULL;
    HI_U32 u32Width = 1280;
    HI_U32 u32Height = 512;
    VI_PIPE_FRAME_SOURCE_E penSource;
    HI_U8 *pUserpicName = "/nfs/vi_chn_w1280_h512.raw";

    s32ViNum  = pstViConfig->as32WorkingViId[0];
    pstViInfo = &pstViConfig->astViInfo[s32ViNum];
    enSnsType    = pstViInfo->stSnsInfo.enSnsType;

    pstVFrameInfo = (VI_USERPIC_ATTR_S*)calloc(1, sizeof(VI_USERPIC_ATTR_S));

    if (BT656_2M_30FPS_8BIT == enSnsType)
    {
        u32LStride = (u32Width + 15) & ( ~(15) ); // 通过对 (u32Width + 15) 和 (~15) 进行按位与操作，可以将宽度调整为最近的16的倍数，这样保证了对齐。
        /*yuv420        
        u32LumaSize = (u32LStride * u32Height);
        u32ChrmSize = (u32CStride * u32Height) >> 2;
        u32Size = u32LumaSize + (u32ChrmSize << 1);
        //*/

        u32LumaSize = (u32LStride * u32Height);   // Y 分量的大小
        u32CStride  =  u32LStride;
        u32ChrmSize = (u32CStride * u32Height);   // UV 分量的大小，和 Y 分量相同
        u32Size = u32LumaSize + u32ChrmSize;      // 总大小，即 Y + UV 分量

        info("u32LumaSize:%u,[%ux%u], u32CStride:%u, u32ChrmSize:%u, u32Size:%u, Format:%d.\n", u32LumaSize, u32LStride, u32Height, u32CStride, u32ChrmSize, u32Size,  pstViConfig->astViInfo->stPipeInfo.enPixFmt);
        /* get video buffer block form common pool */
        VbBlk = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, u32Size, NULL);
        if (VB_INVALID_HANDLE == VbBlk)
        {
            SAMPLE_PRT("get YUV vb block failed\n");
            return HI_FAILURE;
        }

        g_VbBlk = VbBlk;

        /* get physical address*/
        u64PhyAddr = HI_MPI_VB_Handle2PhysAddr(VbBlk);
        if (0 == u64PhyAddr)
        {
            SAMPLE_PRT("get YUV vb block phy addr failed\n");
            return HI_FAILURE;
        }
        SAMPLE_PRT("u64PhyAddr: %#x\n", u64PhyAddr);

        /* get pool id */
        pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId = HI_MPI_VB_Handle2PoolId(VbBlk);
        if (VB_INVALID_POOLID == pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId)
        {
            SAMPLE_PRT("get YUV vb pool id failed\n");
            return HI_FAILURE;
        }

        g_u32PoolId = pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId;

        info("VbBlk;%u, u32PoolId: %u\n", VbBlk, pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);

        /* mmap physical address to virtual address*/
        s32Ret = HI_MPI_VB_MmapPool(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);
        if(s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("get YUV vb pool id failed with: 0x%x\n", s32Ret);
            return HI_FAILURE;
        }

        s32Ret = HI_MPI_VB_GetBlockVirAddr(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId, u64PhyAddr, (void **)&ppVirAddr);
        if(s32Ret != HI_SUCCESS)
        {
            HI_MPI_VB_ReleaseBlock(VbBlk);
            HI_MPI_VB_MunmapPool(pstVFrameInfo->unUsrPic.stUsrPicFrm.u32PoolId);

            SAMPLE_PRT("HI_MPI_VB_GetBlkVirAddr failed with: %#x", s32Ret);
            return HI_FAILURE;
        }
        SAMPLE_PRT("ppVirAddr: %#x", ppVirAddr);

        /* now you need get YUV Semi Palnar Data ,fill them to the virtual address */
        puv = malloc(u32Size);
        if(puv == NULL)
        {
            SAMPLE_PRT("pyuv malloc failed");
            return HI_FAILURE;
        }

        p = ppVirAddr;
        fpic = fopen(pUserpicName,"rb");
        if (fpic == NULL)
        {
            SAMPLE_PRT("can't open file %s", pUserpicName);
            return HI_FAILURE;
        }

        /*捋一捋*/
        if(pstViConfig->astViInfo->stPipeInfo.enPixFmt == PIXEL_FORMAT_YVU_SEMIPLANAR_422 || 1) //按nv16存放数据,test
        {
            // 读取 Y 分量
            fread(p, 1, u32Height * u32LStride, fpic);

            // 读取 UV 分量
            fread(puv, 1, u32Height * u32LStride, fpic);
            pu = puv;  // U 分量起始位置
            pv = puv + 1;  // V 分量起始位置（因为 NV16 是交替存储，V 在 U 后的一个字节）

            // 指向存储 UV 分量的位置
            p = ppVirAddr + (u32Height * u32LStride);

            // 遍历每一行
            for (i = 0; i < u32Height; i++)  // 对于 YUV422，每一行都有 UV 数据
            {
                for (j = 0; j < (u32Width >> 1); j++)  // 每两个像素共享一个 U 和 V
                {
                    p[j * 2] = pu[j * 2];    // 偶数位存放 U 分量
                    p[j * 2 + 1] = pv[j * 2]; // 奇数位存放 V 分量
                }

                pu += u32LStride; // NV16 中，每行都有完整的 U/V 数据
                pv += u32LStride;
                p += u32LStride;
            }
        }
        else  //统一按yuv420处理
        {
            /* read the data of Y component*/
            fread(p, 1, u32Height * u32LStride, fpic);

            /* read the data of UV component*/
            fread(puv, 1, (u32Height * u32LStride) >> 1, fpic);
            pu = puv;
            pv = puv + ((u32Height * u32LStride) >> 2);

            p = ppVirAddr + (u32Height * u32LStride);

            for (i = 0; i < (u32Height >> 1); i++)
            {
                for (j=0; j<(u32Width >> 1); j++)
                {
                    p[j*2+1] = pu[j];
                    p[j*2+0] = pv[j];
                }

                pu += u32LStride >> 1; //u32YStride
                pv += u32LStride >> 1;
                p  += u32LStride;
            }
        }
        

        free(puv);
        puv = HI_NULL;
        fclose(fpic);

        pstVFrameInfo->enUsrPicMode = VI_USERPIC_MODE_PIC;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[0] = u64PhyAddr;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[1] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[0] + u32LumaSize;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[2] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64PhyAddr[1] + u32ChrmSize;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[0] = ppVirAddr;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[1] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[0] + u32LumaSize;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[2] = pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u64VirAddr[1] + u32ChrmSize;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Width = u32Width;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Height = u32Height;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[0] = u32LStride;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[1] = u32LStride;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.u32Stride[2] = u32LStride;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enCompressMode = COMPRESS_MODE_NONE;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enField = VIDEO_FIELD_FRAME;
        pstVFrameInfo->unUsrPic.stUsrPicFrm.stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_422;

        HI_MPI_VI_GetPipeFrameSource(0, &penSource);
        SAMPLE_PRT("PIPE_FRAME_SOURCE: %d\n", penSource);

        // s32Ret = HI_MPI_VI_SetPipeFrameSource(0, VI_PIPE_FRAME_SOURCE_DEV);
        // if (HI_SUCCESS != s32Ret)
        // {
        //     SAMPLE_PRT("HI_MPI_VI_SetPipeFrameSource failed with: 0x%x\n", s32Ret);
        //     return HI_FAILURE;
        // }        

        /* first set user pic info*/
        s32Ret = HI_MPI_VI_SetUserPic(0, pstVFrameInfo);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_SetUserPic failed with: 0x%x\n", s32Ret);
            return HI_FAILURE;
        }

        /* enable insert user pic if you need */
        s32Ret = HI_MPI_VI_EnableUserPic(0);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_EnableUserPic failed with: 0x%x\n", s32Ret);
            return HI_FAILURE;
        }
    }
    else
    {
        /* disable insert user pic if you don't need */
        s32Ret = HI_MPI_VI_DisableUserPic(0);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_DisableUserPic failed with: 0x%x\n", s32Ret);
            return HI_FAILURE;
        }
    }

    return s32Ret;
}

#define xh 1
HI_S32 SAMPLE_VIO_ViOnlineVpssOnlineRoute(HI_U32 u32VoIntfType)
{
    HI_S32             i, s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = INUPT_PIXEL_FORMAT_YVU;//PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;//VI_ONLINE_VPSS_OFFLINE;//VI_OFFLINE_VPSS_ONLINE;//VI_ONLINE_VPSS_ONLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VENC_CHN           VencChn[1]  = {1};
    PAYLOAD_TYPE_E     enType      = PT_H264;
    SAMPLE_RC_E        enRcMode    = SAMPLE_RC_CBR;
    HI_U32             u32Profile  = 0;
    HI_BOOL            bRcnRefShareBuf = HI_TRUE;
    VENC_GOP_ATTR_S    stGopAttr;
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    unsigned char* pStremData = NULL;
    int nSize = 0;
    int j = 0;
    int kk;
    HI_S32             s32MilliSec = 4000;
    HI_U32             u32CapCnt = 0;
    HI_S32             s32DumpCnt = 0;
    VI_CMP_PARAM_S     stCmpPara;
    VIDEO_FRAME_INFO_S astFrame[MAX_FRM_CNT];
    ISP_DIS_ATTR_S     stDISAttr;
    struct timeval tv1, tv2, tv3, tv4, tv5;
    struct tm *pLocalTime;
    time_t timep;
    char string[16] = {0};
    
    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }
    SAMPLE_PRT("get picture size by sensor type:%d , enPicSize:%d\n", stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, enPicSize);
    
    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }
     printf("stSize->width = %d\n", stSize.u32Width);
    printf("stSize->height = %d\n", stSize.u32Height);
    stSize.u32Width = 640;
    stSize.u32Height = 512;
    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              =1;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_420, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize ;
    stVbConf.astCommPool[0].u32BlkCnt   = 3;
/***8gaidong */
#if 0
    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width , stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_422, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 3;
#endif
    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    SAMPLE_PRT("[0920]: stSize.w/h = (%d, %d)-, u64BlkSize[0] = [%lld][%u], , u64BlkSize[1] = [%lld][%u] !\n", \
        stSize.u32Width, stSize.u32Height,  stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize);

    #if 1
    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = DYNAMIC_RANGE_SDR8;
    stVoConfig.enVoIntfType = VO_INTF_BT656;
    stVoConfig.enIntfSync   = VO_OUTPUT_PAL;
    stVoConfig.u32DisBufLen = 3;
    stVoConfig.enPicSize = PIC_D1_PAL;//PIC_D1_PAL;//
    
    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    /*vpss bind vo*/
   // s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VPSS_CHN0, stVoConfig.VoDev, VoChn);//VPSS_CHN1
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VPSS_CHN1, stVoConfig.VoDev, VoChn);
    //s32Ret = SAMPLE_COMM_VI_Bind_VO(ViPipe, ViChn, stVoConfig.VoDev, VoChn);
    //stDISAttr.bEnable = HI_TRUE;
    //HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);
#endif

    #if 1

    /*config venc */
    stGopAttr.enGopMode  = VENC_GOPMODE_NORMALP; //VENC_GOPMODE_SMARTP
    stGopAttr.stNormalP.s32IPQpDelta = 2;
    enPicSize = PIC_640x512;

    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enType, enPicSize, enRcMode, u32Profile,bRcnRefShareBuf, &stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start venc failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }
    #if 0
        s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn[0]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc bind Vpss failed. s32Ret: 0x%x !n", s32Ret);
            goto EXIT3;
        }
    #endif
#endif
    //usleep(1000000);
    HH_OSD_Init(); 
    gettimeofday(&tv1, NULL);
    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }
    
    gettimeofday(&tv2, NULL);
    printf("vi start use %d ms\n",((tv2.tv_usec -tv1.tv_usec) / 1000) + 1000*(tv2.tv_sec - tv1.tv_sec));
    while(1) {
        kk++;
        #if 0
        if(kk%10 == 0) {
            usleep(200000);
        }
        #endif
        //usleep(40000);
        for(int i = 0; i < xh; i++) {
            gettimeofday(&tv3, NULL);
            s32Ret = HI_MPI_VI_GetChnFrame(0, 0, &astFrame[i], -1);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
                goto EXIT;
            }
            gettimeofday(&tv4, NULL);
            astFrame[i].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
            #if 0 
            printf("frame.timerf = %d, frame.PTS= %d\n", astFrame[i].stVFrame.u32TimeRef, astFrame[i].stVFrame.u64PTS);
            #endif
            frame_no = astFrame[i].stVFrame.u32TimeRef;
            gettimeofday(&tv5, NULL);
            time(&timep);
            timep += 8*60*60; //utc-->beijing
            pLocalTime = localtime(&timep);
            #if 0
            printf("cature time[%d] :%04d-%02d-%02d ",  frame_no, 1900+pLocalTime->tm_year, 1+pLocalTime->tm_mon, pLocalTime->tm_mday);
            printf("%02d:%02d:%02d:%03d\n", pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv5.tv_usec / 1000);
            printf("vi get frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
            #endif
        }
        //HI_MPI_VO_SendFrame(0, 0, &astFrame[0], -1);
    for(int i = 0; i < xh ; i++) {
        gettimeofday(&tv3, NULL);
        HI_MPI_VENC_SendFrame(VencChn[0], &astFrame[i], -1);
        sprintf(string, "%d\n", astFrame[0].stVFrame.u32TimeRef);
        #if 0
        printf("insert data = %s\n", string);
        #endif
        s32Ret = HI_MPI_VENC_InsertUserData(VencChn[0], string, sizeof(string));
        if(HI_SUCCESS != s32Ret) {
            printf("venc insert data failed\n");
        }
    venc_data:
        s32Ret = HI_MPI_VENC_QueryStatus(VencChn[0], &stStat);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[%d] failed with %#x!\n", VencChn[0], s32Ret);
            break;
        }
        //printf("stStat.u32CurPacks = %d\n", stStat.u32CurPacks);
        if(0 == stStat.u32CurPacks) {
            //printf("wait venc data\n");
            goto venc_data;
        }
        stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
        if (NULL == stStream.pstPack)
        {
            SAMPLE_PRT("malloc stream pack failed!\n");
            break;
        }
        HH_OSD_All_Refresh();
        stStream.u32PackCount = stStat.u32CurPacks;
        s32Ret = HI_MPI_VENC_GetStream(VencChn[0], &stStream, -1);
        if (HI_SUCCESS != s32Ret)
        {
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                            s32Ret);
            break;
        }
        gettimeofday(&tv4, NULL);
        #if 0
        printf("venc get data use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        gettimeofday(&tv3, NULL);
        for (j = 0; j < stStream.u32PackCount; j++)
		{
			pStremData = (unsigned char*)stStream.pstPack[j].pu8Addr+stStream.pstPack[j].u32Offset;
			nSize = stStream.pstPack[j].u32Len-stStream.pstPack[j].u32Offset;
            //printf("nSzie = %d\n", nSize);            
			s32Ret = rtsp_sever_tx_video(g_rtsplive, session, pStremData, nSize, stStream.pstPack[j].u64PTS);
		}
        gettimeofday(&tv4, NULL);
        #if 0
        printf("venc rtsp send one frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        s32Ret = HI_MPI_VENC_ReleaseStream(VencChn[0], &stStream);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            break;
        }
        free(stStream.pstPack);
        stStream.pstPack = NULL;
        memset(&stStream, 0, sizeof(stStream));	
    }
        for(int i = 0; i < xh; i++) {
            s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[i]);
        }
        //s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[1]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_ReleaseChnFrame failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }
    }
    /*以下参数用于测试自定义yuv422数据 data->pipe->vi online-offline模式下暂不支持*/
    // pthread_t yuvThread;
    // if (pthread_create(&yuvThread, NULL, YUV_SendThread, &ViPipe))
    // {
    //     SAMPLE_PRT("Failed to create YUV send thread !\n");
    //     goto EXIT;
    // }

#if 0
    /*作为无视频信号时的插入图片，用于替换pipe源测试*/
    s32Ret = insert_usr_pic(&stViConfig);
    if(HI_SUCCESS != s32Ret)
    {
        err("insert_usr_pic failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }
#endif

#if 0
    stSize.u32Width = 640;
    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = VPSS_OUTPUT_PIXFMT;
    stVpssGrpAttr.u32MaxW                        =  stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        =  stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = (stSize.u32Width+100);
    astVpssChnAttr[VpssChn].u32Height                   = (stSize.u32Height+100);
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

#if 0
    astVpssChnAttr[VPSS_CHN1].u32Width                    = stSize.u32Width;//(stSize.u32Width-80);//720;
    astVpssChnAttr[VPSS_CHN1].u32Height                   = stSize.u32Height;//(stSize.u32Height-64);//576;
    astVpssChnAttr[VPSS_CHN1].enChnMode                   = VPSS_CHN_MODE_USER;
    // astVpssChnAttr[VPSS_CHN1].bSpEn                       = HI_FALSE;

    astVpssChnAttr[VPSS_CHN1].enCompressMode              = enCompressMode;
    astVpssChnAttr[VPSS_CHN1].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VPSS_CHN1].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VPSS_CHN1].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//enPixFormat;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].u32Depth                    = 8;
    astVpssChnAttr[VPSS_CHN1].bMirror                     = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].bFlip                       = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].stAspectRatio.enMode        = ASPECT_RATIO_NONE;
    abChnEnable[1] = HI_TRUE;
#endif

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }
#endif
#define WRAP_BUF_LEN    (192)
#if 0
    VPSS_LOW_DELAY_INFO_S pstLowDelayInfo;
    VPSS_CHN_BUF_WRAP_S pstVpssChnBufWrap;

    memset_s(&pstLowDelayInfo, sizeof(VPSS_LOW_DELAY_INFO_S), 0, sizeof(VPSS_LOW_DELAY_INFO_S));
    s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(1) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    pstLowDelayInfo.bEnable = HI_TRUE;
    pstLowDelayInfo.u32LineCnt = WRAP_BUF_LEN;
    s32Ret = HI_MPI_VPSS_SetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_SetLowDelayAttr(%d, %d) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        VpssGrp, VpssChn, s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(2) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    /* #################################################################### */

    memset_s(&pstVpssChnBufWrap, sizeof(VPSS_CHN_BUF_WRAP_S), 0, sizeof(VPSS_CHN_BUF_WRAP_S));
    s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(1) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);

    pstVpssChnBufWrap.bEnable = HI_TRUE;
    pstVpssChnBufWrap.u32BufLine = WRAP_BUF_LEN;
    pstVpssChnBufWrap.u32WrapBufferSize = VPSS_GetWrapBufferSize(IN_WIDTH, IN_HEIGHT, WRAP_BUF_LEN, VPSS_OUTPUT_PIXFMT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, 8);
    s32Ret = HI_MPI_VPSS_SetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_SetChnBufWrapAttr(%d, %d) return [0x%x], bEn = [%d], (%d)[%d] !\n", VpssGrp, VpssChn, s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);

    s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(2) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);
#else
// VPSS_LOW_DELAY_INFO_S pstLowDelayInfo;
// VPSS_CHN_BUF_WRAP_S pstVpssChnBufWrap;

// memset_s(&pstLowDelayInfo, sizeof(VPSS_LOW_DELAY_INFO_S), 0, sizeof(VPSS_LOW_DELAY_INFO_S));
// s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
// SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(1) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
//     s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

// memset_s(&pstVpssChnBufWrap, sizeof(VPSS_CHN_BUF_WRAP_S), 0, sizeof(VPSS_CHN_BUF_WRAP_S));
// s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
// SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(1) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
//     pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);
#endif
#if 0
     VPSS_CROP_INFO_S stVpssCropInfo;

     stVpssCropInfo.bEnable = HI_TRUE;
     stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;//绝对坐标模式
     stVpssCropInfo.stCropRect.s32X = 640;
     stVpssCropInfo.stCropRect.s32Y = 512;
     stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width - 640;
     stVpssCropInfo.stCropRect.u32Height = stSize.u32Height - 512 ;
     s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);
#endif
    /*vi bind vpss*/
#if 0
     s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
         goto EXIT2;
     }
#endif

#if 0
     s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &astFrame[0], s32MilliSec);
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
     }
     else {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() done. s32Ret: [0x%x] !\n", s32Ret);
         VIO_VIchn_frame_Save(&astFrame[0], 0);
         s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe, ViChn, &astFrame[0]);
     }
#endif
// #else

    // SAMPLE_DUMP_INIT(HI_TRUE);

    // /* get VI frame  */
    // VIO_SAVE_FILE(ViPipe);
    
    // SAMPLE_DUMP_INIT(HI_FALSE);

    // SAMPLE_DUMP_Proc();
    // SAMPLE_COMM_VI_StartDumpRawThread(ViPipe, 25, "vot");
    // SAMPLE_PRT("Start Dump Raw Thread().\n");
    // sleep(5);
    // SAMPLE_PRT("Dump Raw Thread() done.\n");
    // SAMPLE_COMM_VI_StopDumpRawThread();

#if 0
    const char *outputFile = "/nfs/save_zstd.raw";
    pthread_t thread;
    ThreadParams params = {ViPipe, ViChn, -1, outputFile};

    if (pthread_create(&thread, NULL, vi_capture_thread, &params) != 0) {
        perror("Failed to create thread");
        goto EXIT6;
    }else
    {
        SAMPLE_PRT("Start vi_capture_thread Thread.\n");
    }

    int sock = udp_send_init();
    params.sock = sock;
    pthread_t thread_udp_send;
    if(pthread_create(&thread_udp_send, NULL, send_udp_packet_progress, (HI_VOID*)&params) != 0)
    {
        err("创建线程失败!\n");
        // free(pu8VirAddr);
        goto EXIT6;
    }

    s32Ret = HI_MPI_IVE_CSC(&IveHandle, &g_sys_conf.stSrc_yvu420_packet, &g_sys_conf.stDst_bgr_packet, &stCscCtrl, bInstant);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_CSC failed with error code %#x\n", s32Ret);
    }

    s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_Query failed with error code %#x\n", s32Ret);
    }
#endif

#if 0
    //save vpss data
    s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &astFrame[0], 1000);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
    }
    else {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() done. s32Ret: [0x%x] enPixelFormat:%d!\n", s32Ret, astFrame[0].stVFrame.enPixelFormat);
        // 将物理地址转换为虚拟地址
        astFrame[0].stVFrame.u64VirAddr[0] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
        if (astFrame[0].stVFrame.u64VirAddr[0] == NULL) {
            printf("HI_MPI_SYS_Mmap failed\n");
             goto EXIT6;
        }

        if (astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height / 2);
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                 goto EXIT6;
            }
        }else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height );
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                 goto EXIT6;
            }
        }

        save_frame(&(astFrame[0].stVFrame), "/nfs/vpss.yuv");

        int ret = HI_MPI_VENC_SendFrame( 1, &(astFrame[0].stVFrame), -1);
        if (HI_SUCCESS != ret)
        {
            printf("HI_MPI_VENC_SendFrame, s32Ret = [0x%x].\n", ret);
        }

        // 释放映射的内存
        HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
        if (astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
            HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height / 2);
        }else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
            HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height);
        }

        s32Ret = HI_MPI_VPSS_ReleaseChnFrame(VpssGrp, VpssChn, &astFrame[0]);
    }
#endif

#if 0
    s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, sizeof(VencChn)/sizeof(VENC_CHN));
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Get venc stream failed!\n");
        goto EXIT6;
    }
#endif
    // HH_OSD_Init(); 
	// while(1){
	// 	HH_OSD_All_Refresh();
	// 	usleep(5000);
	// }

while(1){
    //HH_OSD_All_Refresh();
    usleep(5000);
}
    PAUSE();

#if VOT_VENC_EN
    SAMPLE_COMM_VENC_StopGetStream();
#endif

#if VOT_VPSS_EN
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
#endif

EXIT6:
#if VOT_VO_EN
    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VPSS_CHN1, stVoConfig.VoDev, VoChn);
#endif

EXIT5:
#if VOT_VO_EN
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
#endif

EXIT4:
#if VOT_VENC_EN
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn[0]);
#endif

EXIT3:
#if VOT_VENC_EN
    SAMPLE_COMM_VENC_Stop(VencChn[0]);
#endif

EXIT2:
#if VOT_VPSS_EN
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
#endif

EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

void *timer_server(void)
{
    int sockfd, bind_sockfd;
    int ret;
    int data = 1;
    char buf[128];
    struct sockaddr_in serveraddr, bindaddr, check_addr, inaddr;
    struct timeval tv;
    struct tm *pLocalTime;
    time_t timep;
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        printf("sockfd failed\n");
    }
    socklen_t addrlen = sizeof(serveraddr);
    socklen_t addrlen_b = sizeof(bindaddr);
    socklen_t addrlen_c = sizeof(check_addr);
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_addr.s_addr = inet_addr("192.168.110.53");
    printf("inet_ntoa(c->peer_addr) %s\n", inet_ntoa(serveraddr.sin_addr));
    serveraddr.sin_port = htons(8554);
    
    bind_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    bindaddr.sin_family = AF_INET;
    bindaddr.sin_port = htons(8854);
    bindaddr.sin_addr.s_addr = INADDR_ANY;
    bind(bind_sockfd, (struct sockaddr*)&bindaddr, sizeof(bindaddr));
    
    #if 0
    while(1) {
        ret = recvfrom(bind_sockfd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&bindaddr, &addrlen_b);
        printf("buf = %s\n", buf);
        usleep(100000);
    }
    #endif
    ret = recvfrom(bind_sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&check_addr, &addrlen_c);
    printf("check addr = %s port = %u buf = %s\n", inet_ntoa(check_addr.sin_addr), ntohs(check_addr.sin_port), buf);
    while(1) {
        memset(&inaddr, 0, sizeof(inaddr));
        inaddr.sin_family = AF_INET;
        inaddr.sin_addr.s_addr = inet_addr("192.168.110.53");
        inaddr.sin_port = check_addr.sin_port;
        gettimeofday(&tv, NULL);
        time(&timep);
        timep += 8*60*60;
        pLocalTime = localtime(&timep);
        sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d:%03d", 1900+pLocalTime->tm_year, 
            1+pLocalTime->tm_mon, pLocalTime->tm_mday, pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv.tv_usec / 1000);
        ret = sendto(bind_sockfd, buf, strlen(buf), 0, (struct sockaddr*)&inaddr, sizeof(inaddr));

        usleep(500);
    }
}
#define DEBUG_P
#define vb_mem_test
#ifdef vb_mem_test
#define phy0_comm_addr 0x441f0000
#define phy0_blk_size 0x78000
#define phy0_blk_cnt 3


void mmp_mem()
{
    char *map_base0[phy0_blk_cnt];
    char *temp_buf;
    int i , j, k;
    unsigned long rol = 0;
    FILE       *pfile = NULL;
    temp_buf = (char*)malloc(phy0_blk_size*sizeof(char));
    memset(temp_buf, 0, phy0_blk_size);
    #if 1
    map_base0[0] = (char*)SAMPLE_SYS_IOMmap(phy0_comm_addr, phy0_blk_size);
    map_base0[1] = (char*)SAMPLE_SYS_IOMmap(phy0_comm_addr+phy0_blk_size*1, phy0_blk_size);
    map_base0[2] = (char*)SAMPLE_SYS_IOMmap(phy0_comm_addr+phy0_blk_size*2, phy0_blk_size);
    if(map_base0[0] == MAP_FAILED) {
        printf("map base0 failed\n");
    }
    if(map_base0[1] == MAP_FAILED) {
        printf("map base1 failed\n");
    }
    if(map_base0[2] == MAP_FAILED) {
        printf("map base2 failed\n");
    }
    #endif
    printf("     ");
    for(i = 0; i < 16; i++) {
            printf("%02x    ", i);
        }
    printf("\n");
    pfile = fopen("/nfs/test_yuv", "wb");
    if (pfile == NULL) {
        printf("open pfile failed\n");
    }
    while(1) {
        #if 1
        for(i = 0; i < 16; i++) {;
            printf("0x%02x ", map_base0[i*rol]);
        }
        printf("\n");
        rol++;
        if (rol*16 > 16*16) {
            rol = 0;
            printf("\n");
        }
        
        for(i = 0; i < 3; i++){
            memcpy(temp_buf, map_base0[i], phy0_blk_size);
            //fwrite(temp_buf, phy0_blk_size, 1, pfile);
            //SAMPLE_SYS_Munmap(map_base0[i], phy0_blk_size);
            usleep(25000);
        }
        #endif
    }

    free(temp_buf);
}
#endif
void *vio_process(void)
{
    HI_S32             i, s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = INUPT_PIXEL_FORMAT_YVU;//PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    #ifdef IMX_335
    VI_VPSS_MODE_E     enMastPipeMode = VI_OFFLINE_VPSS_ONLINE;//VI_ONLINE_VPSS_OFFLINE;//VI_OFFLINE_VPSS_ONLINE;//VI_ONLINE_VPSS_ONLINE;
    #endif
    #ifdef BT_656
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;//VI_ONLINE_VPSS_OFFLINE;//VI_OFFLINE_VPSS_ONLINE;//VI_ONLINE_VPSS_ONLINE;
    #endif
    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VENC_CHN           VencChn[1]  = {1};
    PAYLOAD_TYPE_E     enType      = PT_H264;
    SAMPLE_RC_E        enRcMode    = SAMPLE_RC_CBR;
    HI_U32             u32Profile  = 0;
    HI_BOOL            bRcnRefShareBuf = HI_TRUE;
    VENC_GOP_ATTR_S    stGopAttr;
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    unsigned char* pStremData = NULL;
    int nSize = 0;
    int j = 0;
    int kk;
    HI_S32             s32MilliSec = 4000;
    HI_U32             u32CapCnt = 0;
    HI_S32             s32DumpCnt = 0;
    VI_CMP_PARAM_S     stCmpPara;
    VIDEO_FRAME_INFO_S astFrame[MAX_FRM_CNT];
    ISP_DIS_ATTR_S     stDISAttr;
    struct timeval tv1, tv2, tv3, tv4, tv5;
    struct tm *pLocalTime;
    time_t timep;
    char string[16] = {0};
    VI_PIPE_STATUS_S pie_status;
    HI_U64  u64PhyAddr;
    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;
    printf("vio_provcess\n");
    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }
    SAMPLE_PRT("get picture size by sensor type:%d , enPicSize:%d\n", stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, enPicSize);
    
    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }
     printf("stSize->width = %d\n", stSize.u32Width);
    printf("stSize->height = %d\n", stSize.u32Height);
    //stSize.u32Width = 640;
    //stSize.u32Height = 512;
    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              =1;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_420, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize ;
    stVbConf.astCommPool[0].u32BlkCnt   = 3;
/***8gaidong */
#if 0
    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width , stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_422, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 3;
#endif
    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    SAMPLE_PRT("[0920]: stSize.w/h = (%d, %d)-, u64BlkSize[0] = [%lld][%u], , u64BlkSize[1] = [%lld][%u] !\n", \
        stSize.u32Width, stSize.u32Height,  stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize);

    #if 1
    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = DYNAMIC_RANGE_SDR8;
    stVoConfig.enVoIntfType = VO_INTF_BT656;
    stVoConfig.enIntfSync   = VO_OUTPUT_PAL;
    stVoConfig.u32DisBufLen = 3;
    stVoConfig.enPicSize = PIC_D1_PAL;//PIC_D1_PAL;//
    
    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    /*vpss bind vo*/
   // s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VPSS_CHN0, stVoConfig.VoDev, VoChn);//VPSS_CHN1
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VPSS_CHN1, stVoConfig.VoDev, VoChn);
    //s32Ret = SAMPLE_COMM_VI_Bind_VO(ViPipe, ViChn, stVoConfig.VoDev, VoChn);
    //stDISAttr.bEnable = HI_TRUE;
    //HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);
#endif

    #if 1

    /*config venc */
    stGopAttr.enGopMode  = VENC_GOPMODE_NORMALP; //VENC_GOPMODE_SMARTP
    stGopAttr.stNormalP.s32IPQpDelta = 2;
    //enPicSize = PIC_640x512;

    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enType, enPicSize, enRcMode, u32Profile,bRcnRefShareBuf, &stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start venc failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }
    #if 0
        s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn[0]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc bind Vpss failed. s32Ret: 0x%x !n", s32Ret);
            goto EXIT3;
        }
    #endif
#endif
    //usleep(1000000);
    
    char *map_base0;
    char *temp_buf;
    char *mp_ptr[3];
    #if 1
    temp_buf = (char*)malloc(phy0_blk_size*sizeof(char));
    map_base0 = (char*)SAMPLE_SYS_IOMmap(phy0_comm_addr, phy0_blk_size*phy0_blk_cnt);
        if(map_base0 == MAP_FAILED) {
            printf("map base0 failed\n");
        }
    mp_ptr[0] = map_base0;
    mp_ptr[1] = map_base0 + phy0_blk_size;
    mp_ptr[2] = map_base0 + phy0_blk_size*2;
    #endif
    gettimeofday(&tv1, NULL);
    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }
    
    gettimeofday(&tv2, NULL);
    printf("vi start use %d ms\n",((tv2.tv_usec -tv1.tv_usec) / 1000) + 1000*(tv2.tv_sec - tv1.tv_sec));

    #ifdef vb_mem_test
    //mmp_mem();
    #endif
    
    //memset(temp_buf, 0, phy0_blk_size);
    
    HH_OSD_Init(); 
    #if 0
    s32Ret = SAMPLE_COMM_VI_Bind_VENC(ViPipe, ViChn, VencChn[0]);
    if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("vi bind venc failed for %#x!\n", s32Ret);
     }
     #endif
    //sleep(5);
    #ifdef BT_656
    int kflg = 0;
    while(1) {
        kk++;
        #if 0
        
        vi_status:
        s32Ret = HI_MPI_VI_QueryPipeStatus(0, &pie_status);
        if(s32Ret != 0) {
            printf("get vi pipe status failed\n");
        } else {
            printf("get vi pipe status success\n");
            printf("pipe->intr = %d\n", pie_status.u32IntCnt);
            if(kflg == pie_status.u32IntCnt) {
                gettimeofday(&tv3, NULL);
            } else {
                gettimeofday(&tv4, NULL);
                kflg = pie_status.u32IntCnt;
                printf("vi intr gap %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
            }
            //kflg = pie_status.u32IntCnt;
            #if 0
            s32Ret = HI_MPI_VI_GetChnFrame(0, 0, &astFrame[0], 10);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
                //goto EXIT;
            } else {
                printf("get vi frame success\n");
                HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[0]);
            }
            #endif
        }
        goto vi_status;
        #endif
        #if 0
        for(int i = 0; i < xh; i++) {
		printf("geti frame\n");
            gettimeofday(&tv3, NULL);
            s32Ret = HI_MPI_VI_GetChnFrame(0, 0, &astFrame[i], -1);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
                goto EXIT;
            }
            gettimeofday(&tv4, NULL);
            astFrame[i].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
            #ifdef DEBUG_P
            printf("frame.timerf = %d, frame.PTS= %d\n", astFrame[i].stVFrame.u32TimeRef, astFrame[i].stVFrame.u64PTS);
            #endif
            frame_no = astFrame[i].stVFrame.u32TimeRef;
            gettimeofday(&tv5, NULL);
            time(&timep);
            timep += 8*60*60; //utc-->beijing
            pLocalTime = localtime(&timep);
            #ifdef DEBUG_P
            printf("cature time[%d] :%04d-%02d-%02d ",  frame_no, 1900+pLocalTime->tm_year, 1+pLocalTime->tm_mon, pLocalTime->tm_mday);
            printf("%02d:%02d:%02d:%03d\n", pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv5.tv_usec / 1000);
            printf("vi get frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
            #endif
            //VIO_VIchn_frame_Save(&astFrame[i], 8);
        }
        //HI_MPI_VO_SendFrame(0, 0, &astFrame[0], -1);
        #endif
        
    #if 0
    FILE       *pfile = NULL;    
    pfile = fopen("/nfs/test_yuv", "wb");
    VB_POOL_CONFIG_S stVbPoolCfg;
    VB_POOL Pool;
    VB_BLK hBlkHdl;
    HI_U32 u32LumaSize, u32ChromaSize;
    HI_U32 u32UVHeight;
    HI_U32 u32Row;
    HI_U8 *pDst;
    HI_U8 *pSrc;
    SAMPLE_VO_VIDEO_FRAME_STRIDE stStride;
    memset(&stVbPoolCfg, 0, sizeof(VB_POOL_CONFIG_S));
    stVbPoolCfg.u64BlkSize = 640*512*2;
    stVbPoolCfg.u32BlkCnt = 6;
    stVbPoolCfg.enRemapMode = VB_REMAP_MODE_NONE;
    Pool = HI_MPI_VB_CreatePool(&stVbPoolCfg);
    if (Pool == VB_INVALID_POOLID) {
        SAMPLE_PRT("HI_MPI_VB_CreatePool fail\n");
        return HI_NULL;
    }
    printf("pool id = %d\n", Pool);
    while(1){
        
        for(int blk_cnt = 0; blk_cnt < 3; blk_cnt++) {
            #if 0
            memcpy(temp_buf, map_base0, phy0_blk_size);
            for(int i = 0; i < 16; i++) {
                printf("0x%02x ", temp_buf[i]);
            }
            printf("\n");
            
            fwrite(temp_buf, phy0_blk_size, 1, pfile);
            #endif
            gettimeofday(&tv3, NULL);
            memset(&astFrame[0], 0, sizeof(VIDEO_FRAME_INFO_S));   
            hBlkHdl = HI_MPI_VB_GetBlock(Pool, 640*512*2, NULL);
            if (hBlkHdl == VB_INVALID_HANDLE) {
                SAMPLE_PRT("get vb fail!!!\n");
                continue;
            }
            astFrame[0].stVFrame.u32Stride[0] = ALIGN_BACK(640, 16);
            astFrame[0].stVFrame.u32Stride[1] = ALIGN_BACK(640, 16);
            astFrame[0].stVFrame.u32Stride[2] = ALIGN_BACK(640, 16);
            stStride.yStride = astFrame[0].stVFrame.u32Stride[0];
            stStride.uStride = astFrame[0].stVFrame.u32Stride[1] >> 1;

            u32LumaSize = 512*astFrame[0].stVFrame.u32Stride[0];
            u32ChromaSize = astFrame[0].stVFrame.u32Stride[0] * 512 / 4;
            astFrame[0].u32PoolId = HI_MPI_VB_Handle2PoolId(hBlkHdl);
            astFrame[0].stVFrame.u64PhyAddr[0] = HI_MPI_VB_Handle2PhysAddr(hBlkHdl);
            astFrame[0].stVFrame.u64PhyAddr[1] = astFrame[0].stVFrame.u64PhyAddr[0] + u32LumaSize;
            astFrame[0].stVFrame.u64PhyAddr[2] = astFrame[0].stVFrame.u64PhyAddr[1] + u32ChromaSize;
        
            astFrame[0].stVFrame.u64VirAddr[0] = (HI_UL)HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[0], 640*512*2);//y
            astFrame[0].stVFrame.u64VirAddr[1] = (HI_UL)astFrame[0].stVFrame.u64VirAddr[0] + u32LumaSize;//u
            astFrame[0].stVFrame.u64VirAddr[2] = (HI_UL)astFrame[0].stVFrame.u64VirAddr[1] + u32ChromaSize;//v

            astFrame[0].stVFrame.enField = 0x03;
            astFrame[0].stVFrame.enCompressMode = COMPRESS_MODE_NONE;
            astFrame[0].stVFrame.u32Width = 640;
            astFrame[0].stVFrame.u32Height = 512;
            astFrame[0].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
            astFrame[0].stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
            astFrame[0].stVFrame.enColorGamut = COLOR_GAMUT_BT709;
            astFrame[0].stVFrame.u32TimeRef = 0;
            astFrame[0].stVFrame.u64PTS = 0;
            astFrame[0].stVFrame.enDynamicRange = DYNAMIC_RANGE_SDR8;
        
            u32UVHeight = 512/2;
            pDst = astFrame[0].stVFrame.u64VirAddr[0];
            pSrc = mp_ptr[i];
            for(u32Row = 0; u32Row < 512; u32Row++) {
                memcpy(pDst, pSrc, 640);
                pDst += stStride.yStride;
                pSrc += 640;
            }
            pDst = astFrame[0].stVFrame.u64VirAddr[1];
            for(u32Row = 0; u32Row < u32UVHeight; u32Row++) {
                memcpy(pDst, pSrc, 640/2);
                pDst += stStride.uStride;
                pSrc += 640/2;
            }
            pDst = astFrame[0].stVFrame.u64VirAddr[2];
            for(u32Row = 0; u32Row < u32UVHeight; u32Row++) {
                memcpy(pDst, pSrc, 640/2);
                pDst += stStride.uStride;
                pSrc += 640/2;
            }
            astFrame[0].stVFrame.u64PTS += 2000;
            astFrame[0].stVFrame.u32TimeRef += 2000;
            //HI_MPI_VI_GetChnFrame(0, 0, &astFrame[0], -1);
        
            //SAMPLE_SYS_Munmap(map_base0, phy0_blk_size*phy0_blk_cnt);
            
            usleep(29000);
            gettimeofday(&tv4, NULL);
            printf("send one frame from vb use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
            
            HI_MPI_VO_SendFrame(0, 0, &astFrame[0], -1);
            s32Ret = HI_MPI_VB_ReleaseBlock(hBlkHdl);
            if(s32Ret != 0) {
                printf("release blk failed 0x%x\n", s32Ret);
            }
            s32Ret = HI_MPI_SYS_Munmap ((HI_VOID *)(HI_UL)astFrame[0].stVFrame.u64VirAddr[0], 640*512*2);
            if(s32Ret != 0) {
                printf("HI_MPI_SYS_Munmap failed 0x%x\n", s32Ret);
            }
        }
    }
    #endif
    for(int i = 0; i < xh ; i++) {
        gettimeofday(&tv3, NULL);
        
        s32Ret = HI_MPI_VI_GetChnFrame(0, 0, &astFrame[i], -1);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }
        gettimeofday(&tv4, NULL);
        astFrame[i].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        HI_MPI_VENC_SendFrame(VencChn[0], &astFrame[i], -1);
        
        sprintf(string, "%d\n", astFrame[0].stVFrame.u32TimeRef);
        #ifdef DEBUG_P
        printf("insert data = %s", string);
        #endif
        s32Ret = HI_MPI_VENC_InsertUserData(VencChn[0], string, strlen(string));
        #ifdef DEBUG_P
        printf("len = %d\n", strlen(string));
        #endif
        if(HI_SUCCESS != s32Ret) {
            printf("venc insert data failed\n");
        }
    venc_data:
        s32Ret = HI_MPI_VENC_QueryStatus(VencChn[0], &stStat);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[%d] failed with %#x!\n", VencChn[0], s32Ret);
            break;
        }
        //printf("stStat.u32CurPacks = %d\n", stStat.u32CurPacks);
        if(0 == stStat.u32CurPacks) {
            //printf("wait venc data\n");
            goto venc_data;
        }
        stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
        if (NULL == stStream.pstPack)
        {
            SAMPLE_PRT("malloc stream pack failed!\n");
            break;
        }
        HH_OSD_All_Refresh();
        stStream.u32PackCount = stStat.u32CurPacks;
        s32Ret = HI_MPI_VENC_GetStream(VencChn[0], &stStream, -1);
        if (HI_SUCCESS != s32Ret)
        {
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                            s32Ret);
            break;
        }
        gettimeofday(&tv4, NULL);
        #ifdef DEBUG_P
        printf("venc get data use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        gettimeofday(&tv3, NULL);
        for (j = 0; j < stStream.u32PackCount; j++)
		{
			pStremData = (unsigned char*)stStream.pstPack[j].pu8Addr+stStream.pstPack[j].u32Offset;
			nSize = stStream.pstPack[j].u32Len-stStream.pstPack[j].u32Offset;
            //printf("nSzie = %d\n", nSize);            
			s32Ret = rtsp_sever_tx_video(g_rtsplive, session, pStremData, nSize, stStream.pstPack[j].u64PTS);
		}
        gettimeofday(&tv4, NULL);
        #ifdef DEBUG_P
        printf("venc rtsp send one frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        printf("\n");
        s32Ret = HI_MPI_VENC_ReleaseStream(VencChn[0], &stStream);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            break;
        }
        free(stStream.pstPack);
        stStream.pstPack = NULL;
        memset(&stStream, 0, sizeof(stStream));	
    }
        for(int i = 0; i < xh; i++) {
            #if 0
            printf("frame.poolid = %d\n", astFrame[i].u32PoolId);
            printf("frame.enModId = %d\n", astFrame[i].enModId);
            printf("frame.phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64PhyAddr[0]);
            u64PhyAddr = astFrame[i].stVFrame.u64PhyAddr[0];
            printf("u64Phyaddr = %ld\n", u64PhyAddr);
            printf("frame.phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64PhyAddr[1]);
            printf("frame.phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64PhyAddr[2]);
            printf("frame.vaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64VirAddr[0]);
            printf("frame.vaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64VirAddr[1]);
            printf("frame.vaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64VirAddr[2]);
            printf("enFiled = %d\n", astFrame[i].stVFrame.enField);
            printf("supplement = %d\n", astFrame[i].stVFrame.stSupplement);
            printf("frame.head phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderPhyAddr[0]);
            printf("frame.head phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderPhyAddr[1]);
            printf("frame.head phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderPhyAddr[2]);
            printf("frame.head vir phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderVirAddr[0]);
            printf("frame.head vir phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderVirAddr[1]);
            printf("frame.head vir phyaddr0 = 0x%lx\n", astFrame[i].stVFrame.u64HeaderVirAddr[2]);
            #endif
            s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[i]);
        }
        //s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[1]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_ReleaseChnFrame failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }
    }
#endif

    #ifdef IMX_335
    while(1) {
        kk++;
        #if 0
        if(kk%10 == 0) {
            usleep(200000);
        }
        #endif
        //usleep(40000);
        for(int i = 0; i < xh; i++) {
            // // gettimeofday(&tv3, NULL);
            // // s32Ret = HI_MPI_VI_GetChnFrame(0, 0, &astFrame[i], -1);
            // //  if (HI_SUCCESS != s32Ret)
            // // {
            // //     SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
            // //     goto EXIT;
            // // }
            // // gettimeofday(&tv4, NULL);
            // // astFrame[i].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
            // #ifdef DEBUG_P
            // //printf("frame.timerf = %d, frame.PTS= %d\n", astFrame[i].stVFrame.u32TimeRef, astFrame[i].stVFrame.u64PTS);
            // #endif
            // frame_no = astFrame[i].stVFrame.u32TimeRef;
            // gettimeofday(&tv5, NULL);
            // time(&timep);
            // timep += 8*60*60; //utc-->beijing
            // pLocalTime = localtime(&timep);
            // #ifdef DEBUG_P
            // printf("cature time[%d] :%04d-%02d-%02d ",  frame_no, 1900+pLocalTime->tm_year, 1+pLocalTime->tm_mon, pLocalTime->tm_mday);
            // printf("%02d:%02d:%02d:%03d\n", pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv5.tv_usec / 1000);
            // printf("vi get frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
            // #endif
        }
        //HI_MPI_VO_SendFrame(0, 0, &astFrame[0], -1);
    for(int i = 0; i < xh ; i++) {
        // gettimeofday(&tv3, NULL);
        // HI_MPI_VENC_SendFrame(VencChn[0], &astFrame[i], -1);
        // sprintf(string, "%d\n", astFrame[0].stVFrame.u32TimeRef);
        // #ifdef DEBUG_P
        // printf("insert data = %s", string);
        // #endif
        // s32Ret = HI_MPI_VENC_InsertUserData(VencChn[0], string, strlen(string));
        // #ifdef DEBUG_P
        // printf("len = %d\n", strlen(string));
        // #endif
        // if(HI_SUCCESS != s32Ret) {
        //     printf("venc insert data failed\n");
        // }
    venc_data:
        printf("1111111\n");
        s32Ret = HI_MPI_VENC_QueryStatus(VencChn[0], &stStat);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[%d] failed with %#x!\n", VencChn[0], s32Ret);
            break;
        }
        printf("stStat.u32CurPacks = %d\n", stStat.u32CurPacks);
        if(0 == stStat.u32CurPacks) {
            printf("wait venc data\n");
            goto venc_data;
        }
        stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
        if (NULL == stStream.pstPack)
        {
            SAMPLE_PRT("malloc stream pack failed!\n");
            break;
        }
        HH_OSD_All_Refresh();
        stStream.u32PackCount = stStat.u32CurPacks;
        s32Ret = HI_MPI_VENC_GetStream(VencChn[0], &stStream, -1);
        if (HI_SUCCESS != s32Ret)
        {
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                            s32Ret);
            break;
        }
        gettimeofday(&tv4, NULL);
        #ifdef DEBUG_P
        printf("venc get data use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        gettimeofday(&tv3, NULL);
        for (j = 0; j < stStream.u32PackCount; j++)
		{
			pStremData = (unsigned char*)stStream.pstPack[j].pu8Addr+stStream.pstPack[j].u32Offset;
			nSize = stStream.pstPack[j].u32Len-stStream.pstPack[j].u32Offset;
            //printf("nSzie = %d\n", nSize);            
			s32Ret = rtsp_sever_tx_video(g_rtsplive, session, pStremData, nSize, stStream.pstPack[j].u64PTS);
		}
        gettimeofday(&tv4, NULL);
        #ifdef DEBUG_P
        printf("venc rtsp send one frame use %d ms\n",((tv4.tv_usec -tv3.tv_usec) / 1000) + 1000*(tv4.tv_sec - tv3.tv_sec));
        #endif
        printf("\n");
        s32Ret = HI_MPI_VENC_ReleaseStream(VencChn[0], &stStream);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
            free(stStream.pstPack);
            stStream.pstPack = NULL;
            break;
        }
        free(stStream.pstPack);
        stStream.pstPack = NULL;
        memset(&stStream, 0, sizeof(stStream));	
    }
        for(int i = 0; i < xh; i++) {
           // s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[i]);
        }
        //s32Ret = HI_MPI_VI_ReleaseChnFrame(0, 0, &astFrame[1]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_ReleaseChnFrame failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }
    }

    #endif
    /*以下参数用于测试自定义yuv422数据 data->pipe->vi online-offline模式下暂不支持*/
    // pthread_t yuvThread;
    // if (pthread_create(&yuvThread, NULL, YUV_SendThread, &ViPipe))
    // {
    //     SAMPLE_PRT("Failed to create YUV send thread !\n");
    //     goto EXIT;
    // }

#if 0
    /*作为无视频信号时的插入图片，用于替换pipe源测试*/
    s32Ret = insert_usr_pic(&stViConfig);
    if(HI_SUCCESS != s32Ret)
    {
        err("insert_usr_pic failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }
#endif

#if 0
    stSize.u32Width = 640;
    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = VPSS_OUTPUT_PIXFMT;
    stVpssGrpAttr.u32MaxW                        =  stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        =  stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = (stSize.u32Width+100);
    astVpssChnAttr[VpssChn].u32Height                   = (stSize.u32Height+100);
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

#if 0
    astVpssChnAttr[VPSS_CHN1].u32Width                    = stSize.u32Width;//(stSize.u32Width-80);//720;
    astVpssChnAttr[VPSS_CHN1].u32Height                   = stSize.u32Height;//(stSize.u32Height-64);//576;
    astVpssChnAttr[VPSS_CHN1].enChnMode                   = VPSS_CHN_MODE_USER;
    // astVpssChnAttr[VPSS_CHN1].bSpEn                       = HI_FALSE;

    astVpssChnAttr[VPSS_CHN1].enCompressMode              = enCompressMode;
    astVpssChnAttr[VPSS_CHN1].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VPSS_CHN1].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VPSS_CHN1].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//enPixFormat;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VPSS_CHN1].u32Depth                    = 8;
    astVpssChnAttr[VPSS_CHN1].bMirror                     = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].bFlip                       = HI_FALSE;
    astVpssChnAttr[VPSS_CHN1].stAspectRatio.enMode        = ASPECT_RATIO_NONE;
    abChnEnable[1] = HI_TRUE;
#endif

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }
#endif
#define WRAP_BUF_LEN    (192)
#if 0
    VPSS_LOW_DELAY_INFO_S pstLowDelayInfo;
    VPSS_CHN_BUF_WRAP_S pstVpssChnBufWrap;

    memset_s(&pstLowDelayInfo, sizeof(VPSS_LOW_DELAY_INFO_S), 0, sizeof(VPSS_LOW_DELAY_INFO_S));
    s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(1) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    pstLowDelayInfo.bEnable = HI_TRUE;
    pstLowDelayInfo.u32LineCnt = WRAP_BUF_LEN;
    s32Ret = HI_MPI_VPSS_SetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_SetLowDelayAttr(%d, %d) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        VpssGrp, VpssChn, s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
    SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(2) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
        s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

    /* #################################################################### */

    memset_s(&pstVpssChnBufWrap, sizeof(VPSS_CHN_BUF_WRAP_S), 0, sizeof(VPSS_CHN_BUF_WRAP_S));
    s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(1) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);

    pstVpssChnBufWrap.bEnable = HI_TRUE;
    pstVpssChnBufWrap.u32BufLine = WRAP_BUF_LEN;
    pstVpssChnBufWrap.u32WrapBufferSize = VPSS_GetWrapBufferSize(IN_WIDTH, IN_HEIGHT, WRAP_BUF_LEN, VPSS_OUTPUT_PIXFMT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, 8);
    s32Ret = HI_MPI_VPSS_SetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_SetChnBufWrapAttr(%d, %d) return [0x%x], bEn = [%d], (%d)[%d] !\n", VpssGrp, VpssChn, s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);

    s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
    SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(2) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
        pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);
#else
// VPSS_LOW_DELAY_INFO_S pstLowDelayInfo;
// VPSS_CHN_BUF_WRAP_S pstVpssChnBufWrap;

// memset_s(&pstLowDelayInfo, sizeof(VPSS_LOW_DELAY_INFO_S), 0, sizeof(VPSS_LOW_DELAY_INFO_S));
// s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn, &pstLowDelayInfo);
// SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr(1) return [0x%x], bEn = [%d], u32LineCnt = [%d] !\n", \
//     s32Ret, pstLowDelayInfo.bEnable, pstLowDelayInfo.u32LineCnt);

// memset_s(&pstVpssChnBufWrap, sizeof(VPSS_CHN_BUF_WRAP_S), 0, sizeof(VPSS_CHN_BUF_WRAP_S));
// s32Ret = HI_MPI_VPSS_GetChnBufWrapAttr(VpssGrp, VpssChn, &pstVpssChnBufWrap);
// SAMPLE_PRT("HI_MPI_VPSS_GetChnBufWrapAttr(1) return [0x%x], bEn = [%d], (%d)[%d] !\n", s32Ret, \
//     pstVpssChnBufWrap.bEnable, pstVpssChnBufWrap.u32BufLine, pstVpssChnBufWrap.u32WrapBufferSize);
#endif
#if 0
     VPSS_CROP_INFO_S stVpssCropInfo;

     stVpssCropInfo.bEnable = HI_TRUE;
     stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;//绝对坐标模式
     stVpssCropInfo.stCropRect.s32X = 640;
     stVpssCropInfo.stCropRect.s32Y = 512;
     stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width - 640;
     stVpssCropInfo.stCropRect.u32Height = stSize.u32Height - 512 ;
     s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);
#endif
    /*vi bind vpss*/
#if 0
     s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
         goto EXIT2;
     }
#endif

#if 0
     s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &astFrame[0], s32MilliSec);
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
     }
     else {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() done. s32Ret: [0x%x] !\n", s32Ret);
         VIO_VIchn_frame_Save(&astFrame[0], 0);
         s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe, ViChn, &astFrame[0]);
     }
#endif
// #else

    // SAMPLE_DUMP_INIT(HI_TRUE);

    // /* get VI frame  */
    // VIO_SAVE_FILE(ViPipe);
    
    // SAMPLE_DUMP_INIT(HI_FALSE);

    // SAMPLE_DUMP_Proc();
    // SAMPLE_COMM_VI_StartDumpRawThread(ViPipe, 25, "vot");
    // SAMPLE_PRT("Start Dump Raw Thread().\n");
    // sleep(5);
    // SAMPLE_PRT("Dump Raw Thread() done.\n");
    // SAMPLE_COMM_VI_StopDumpRawThread();

#if 0
    const char *outputFile = "/nfs/save_zstd.raw";
    pthread_t thread;
    ThreadParams params = {ViPipe, ViChn, -1, outputFile};

    if (pthread_create(&thread, NULL, vi_capture_thread, &params) != 0) {
        perror("Failed to create thread");
        goto EXIT6;
    }else
    {
        SAMPLE_PRT("Start vi_capture_thread Thread.\n");
    }

    int sock = udp_send_init();
    params.sock = sock;
    pthread_t thread_udp_send;
    if(pthread_create(&thread_udp_send, NULL, send_udp_packet_progress, (HI_VOID*)&params) != 0)
    {
        err("创建线程失败!\n");
        // free(pu8VirAddr);
        goto EXIT6;
    }

    s32Ret = HI_MPI_IVE_CSC(&IveHandle, &g_sys_conf.stSrc_yvu420_packet, &g_sys_conf.stDst_bgr_packet, &stCscCtrl, bInstant);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_CSC failed with error code %#x\n", s32Ret);
    }

    s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
    if (s32Ret != HI_SUCCESS){
        printf("HI_MPI_IVE_Query failed with error code %#x\n", s32Ret);
    }
#endif

#if 0
    //save vpss data
    s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &astFrame[0], 1000);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
    }
    else {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() done. s32Ret: [0x%x] enPixelFormat:%d!\n", s32Ret, astFrame[0].stVFrame.enPixelFormat);
        // 将物理地址转换为虚拟地址
        astFrame[0].stVFrame.u64VirAddr[0] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
        if (astFrame[0].stVFrame.u64VirAddr[0] == NULL) {
            printf("HI_MPI_SYS_Mmap failed\n");
             goto EXIT6;
        }

        if (astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height / 2);
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                 goto EXIT6;
            }
        }else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height );
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                 goto EXIT6;
            }
        }

        save_frame(&(astFrame[0].stVFrame), "/nfs/vpss.yuv");

        int ret = HI_MPI_VENC_SendFrame( 1, &(astFrame[0].stVFrame), -1);
        if (HI_SUCCESS != ret)
        {
            printf("HI_MPI_VENC_SendFrame, s32Ret = [0x%x].\n", ret);
        }

        // 释放映射的内存
        HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
        if (astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
            HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height / 2);
        }else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
            HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height);
        }

        s32Ret = HI_MPI_VPSS_ReleaseChnFrame(VpssGrp, VpssChn, &astFrame[0]);
    }
#endif

#if 0
    s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, sizeof(VencChn)/sizeof(VENC_CHN));
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Get venc stream failed!\n");
        goto EXIT6;
    }
#endif
    // HH_OSD_Init(); 
	// while(1){
	// 	HH_OSD_All_Refresh();
	// 	usleep(5000);
	// }

while(1){
    //HH_OSD_All_Refresh();
    usleep(5000);
}
    PAUSE();

#if VOT_VENC_EN
    SAMPLE_COMM_VENC_StopGetStream();
#endif

#if VOT_VPSS_EN
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
#endif

EXIT6:
#if VOT_VO_EN
    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VPSS_CHN1, stVoConfig.VoDev, VoChn);
#endif

EXIT5:
#if VOT_VO_EN
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
#endif

EXIT4:
#if VOT_VENC_EN
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn[0]);
#endif

EXIT3:
#if VOT_VENC_EN
    SAMPLE_COMM_VENC_Stop(VencChn[0]);
#endif

EXIT2:
#if VOT_VPSS_EN
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
#endif

EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}



HI_S32 SAMPLE_VIO_ViOfflineVpssOnline_LDC_Rotation(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = VI_PIPE_PIXFMT;//PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_OFFLINE_VPSS_ONLINE;//VI_ONLINE_VPSS_OFFLINE;//VI_OFFLINE_VPSS_ONLINE

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VPSS_LDCV3_ATTR_S    stLDCV3Attr;
    ROTATION_E           enRotation;


    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = VI_PIPE_PIXFMT;//enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = (stSize.u32Width * stSize.u32Height * 3);//u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 3;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = (stSize.u32Width * stSize.u32Height * 3);//u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 5;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    SAMPLE_PRT("[0920]: stSize.w/h = (%d, %d)-[%d, %d], u64BlkSize[0] = [%lld][%u], , u64BlkSize[1] = [%lld][%u] !\n", \
        stSize.u32Width, stSize.u32Height, IN_WIDTH, IN_HEIGHT, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[0].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize, stVbConf.astCommPool[1].u64BlkSize);

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }
    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.u32DisBufLen = 3;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }


    stLDCV3Attr.stAttr.enViewType = LDC_VIEW_TYPE_ALL;   //LDC_VIEW_TYPE_CROP;
    stLDCV3Attr.stAttr.s32CenterXOffset   = 0;
    stLDCV3Attr.stAttr.s32CenterYOffset   = 0;
    stLDCV3Attr.stAttr.s32DistortionRatio = 200;
    stLDCV3Attr.stAttr.s32MinRatio = 0;


    for (int temp = 1; temp < 4; temp++)
    {
        printf("Enter any key to Enable/Disable LDCV3!!\n");
        getchar();
        stLDCV3Attr.bEnable = temp % 2;
        s32Ret = HI_MPI_VPSS_SetChnLDCV3Attr(VpssGrp, VpssChn, &stLDCV3Attr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VPSS_SetChnLDCV3Attr failed witfh %x\n", s32Ret);
            goto EXIT4;
        }
    }


    for (int temp = 1; temp < 5; temp++)
    {
        printf("Enter any key to ROTATION!!\n");
        getchar();
        enRotation = temp % 4;
        s32Ret = HI_MPI_VPSS_SetChnRotation(VpssGrp, VpssChn, enRotation);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VPSS_SetChnRotation failed witfh %x\n", s32Ret);
            goto EXIT4;
        }
    }
    getchar();

EXIT4:
    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT3:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

HI_S32 SAMPLE_VIO_ViOnlineVpssOffline_ISPDIS(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = INUPT_PIXEL_FORMAT_YVU;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN2;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    ISP_DIS_ATTR_S     stDISAttr;
    HI_S32             s32MilliSec = 4000;
    VIDEO_FRAME_INFO_S astFrame[MAX_FRM_CNT];
    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
   
    if (stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType == BT656_2M_30FPS_8BIT)
    {
        
        SAMPLE_PRT("sensor type bt656\n");
        //stSize.u32Width = 720;
        //stSize.u32Height = 288;
    }

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_422, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 20;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_YVU_SEMIPLANAR_422, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 20;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = VPSS_OUTPUT_PIXFMT;//enPixFormat
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;
    stVpssGrpAttr.stNrAttr.enNrType       = VPSS_NR_TYPE_VIDEO;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 8;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[2] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    VPSS_CROP_INFO_S stVpssCropInfo;

    stVpssCropInfo.bEnable = HI_TRUE;
    stVpssCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
    stVpssCropInfo.stCropRect.s32X = 50;
    stVpssCropInfo.stCropRect.s32Y = 50;
    stVpssCropInfo.stCropRect.u32Width  = stSize.u32Width-100;
    stVpssCropInfo.stCropRect.u32Height = stSize.u32Height-100;
    s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &stVpssCropInfo);

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &astFrame[0], s32MilliSec);
    if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
     }
    else {
         SAMPLE_PRT("HI_MPI_VI_GetChnFrame() done. s32Ret: [0x%x] !\n", s32Ret);
         VIO_VIchn_frame_Save(&astFrame[0], 0);
         s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe, ViChn, &astFrame[0]);
     }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT656;
    stVoConfig.enIntfSync   = VO_OUTPUT_PAL;
    stVoConfig.u32DisBufLen = 3;

    stVoConfig.enPicSize = enPicSize;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &astFrame[0], 1000);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
    }
    else {
        SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame() done. s32Ret: [0x%x] enPixelFormat:%d!\n", s32Ret, astFrame[0].stVFrame.enPixelFormat);
        // 将物理地址转换为虚拟地址
        astFrame[0].stVFrame.u64VirAddr[0] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
        if (astFrame[0].stVFrame.u64VirAddr[0] == NULL) {
            printf("HI_MPI_SYS_Mmap failed\n");
             
        }

        if (astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height / 2);
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                
            }
        }else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
            astFrame[0].stVFrame.u64VirAddr[1] = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[1], astFrame[0].stVFrame.u32Stride[1] * astFrame[0].stVFrame.u32Height );
            if (astFrame[0].stVFrame.u64VirAddr[1] == NULL) {
                printf("HI_MPI_SYS_Mmap failed\n");
                HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[0], astFrame[0].stVFrame.u32Stride[0] * astFrame[0].stVFrame.u32Height);
                
            }
        }

        save_frame(&(astFrame[0].stVFrame), "/nfs/vpss.yuv");
    }
    printf("Enter any key to enable 2Dim-Dis.\n");
    PAUSE();
    stDISAttr.bEnable = HI_TRUE;
    HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);

    printf("Enter any key to Disable 2Dim-Dis.\n");
    PAUSE();
    stDISAttr.bEnable = HI_FALSE;
    HI_MPI_ISP_SetDISAttr(ViPipe, &stDISAttr);
    PAUSE();

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT3:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

HI_S32 SAMPLE_VIO_ViWdrSwitch(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe[2]      = {0, 1};
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    VENC_CHN           VencChn[1]  = {0};
    PAYLOAD_TYPE_E     enType      = PT_H265;
    SAMPLE_RC_E        enRcMode    = SAMPLE_RC_CBR;
    HI_U32             u32Profile  = 0;
    HI_BOOL            bRcnRefShareBuf = HI_FALSE;
    VENC_GOP_ATTR_S    stGopAttr;

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe[0];
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, enCompressMode, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 5;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_FALSE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe[0], ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config venc */
    stGopAttr.enGopMode  = VENC_GOPMODE_SMARTP;
    stGopAttr.stSmartP.s32BgQpDelta  = 7;
    stGopAttr.stSmartP.s32ViQpDelta  = 2;
    stGopAttr.stSmartP.u32BgInterval = 1200;
    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enType, enPicSize, enRcMode, u32Profile, bRcnRefShareBuf,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start venc failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn[0]);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc bind Vpss failed. s32Ret: 0x%x !n", s32Ret);
        goto EXIT4;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT5;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT6;
    }

    s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, sizeof(VencChn)/sizeof(VENC_CHN));
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Get venc stream failed!\n");
        goto EXIT7;
    }

    SAMPLE_PRT("switch to wdr mode========\n");
    getchar();

    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
    SAMPLE_COMM_VI_SwitchMode_StopVI(&stViConfig);

    if (SONY_IMX327_MIPI_2M_30FPS_12BIT == stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType)
    {
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SONY_IMX327_MIPI_2M_30FPS_12BIT_WDR2TO1;
    }
    else if (SONY_IMX327_2L_MIPI_2M_30FPS_12BIT == stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType)
    {
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SONY_IMX327_2L_MIPI_2M_30FPS_12BIT_WDR2TO1;
    }
    else if (SONY_IMX307_MIPI_2M_30FPS_12BIT == stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType)
    {
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SONY_IMX307_MIPI_2M_30FPS_12BIT_WDR2TO1;
    }
    else if (SONY_IMX307_2L_MIPI_2M_30FPS_12BIT == stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType)
    {
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SONY_IMX307_2L_MIPI_2M_30FPS_12BIT_WDR2TO1;
    }
    else if (OMNIVISION_OS05A_MIPI_4M_30FPS_12BIT == stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType)
    {
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = OMNIVISION_OS05A_MIPI_4M_30FPS_10BIT_WDR2TO1;
    }
    else
    {
        SAMPLE_PRT("sensor:%d, not support switch to wdr mode========\n", stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType);
    }

    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode = WDR_MODE_2To1_LINE;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0] = ViPipe[0];
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1] = ViPipe[1];

    SAMPLE_COMM_VI_SwitchMode(&stViConfig);

    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT8;
    }

    SAMPLE_PRT("switch to linear mode========\n");
    getchar();

    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
    SAMPLE_COMM_VI_SwitchMode_StopVI(&stViConfig);

    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SENSOR0_TYPE;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode = WDR_MODE_NONE;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0] = ViPipe[0];
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1] = -1;

    SAMPLE_COMM_VI_SwitchMode(&stViConfig);

    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT8;
    }

    PAUSE();

EXIT8:
    SAMPLE_COMM_VENC_StopGetStream();
EXIT7:
    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT6:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT5:
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn[0]);
EXIT4:
    SAMPLE_COMM_VENC_Stop(VencChn[0]);
EXIT3:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe[0], ViChn, VpssGrp);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}


HI_S32 SAMPLE_VIO_ViWdrOffline(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe[2]      = {0, 1};
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_2To1_LINE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_OFFLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe[0];
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = ViPipe[1];
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, enCompressMode, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 4;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, enCompressMode, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 6;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe[0], ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    SAMPLE_PRT("Exit to wdr mode========\n");
    PAUSE();

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT4:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT3:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe[0], ViChn, VpssGrp);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}


HI_S32 SAMPLE_VIO_FrameModeWdr(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe[2]      = {0, 1};
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_2To1_FRAME;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe[0];
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = ViPipe[1];
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, enCompressMode, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 2;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, enCompressMode, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 3;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe[0], ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    SAMPLE_PRT("Exit to wdr mode========\n");
    PAUSE();

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT4:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT3:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe[0], ViChn, VpssGrp);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}


HI_S32 SAMPLE_VIO_FPN(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret = HI_SUCCESS;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    PIXEL_FORMAT_E     enRawPixFormat = PIXEL_FORMAT_RGB_BAYER_12BPP;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;


    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN1;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];


    SAMPLE_VI_FPN_CALIBRATE_INFO_S stViFpnCalibrateInfo;
    SAMPLE_VI_FPN_CORRECTION_INFO_S stViFpnCorrectionInfo;

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;

    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 3;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, enRawPixFormat, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 3;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = 1920;
    astVpssChnAttr[VpssChn].u32Height                   = 1080;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[VPSS_CHN1] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }


    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync   = VO_OUTPUT_576P50;
    stVoConfig.u32DisBufLen = 3;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }


    stViFpnCalibrateInfo.u32Threshold   = 4095;
    stViFpnCalibrateInfo.u32FrameNum    = 16;
    stViFpnCalibrateInfo.enFpnType      = ISP_FPN_TYPE_FRAME;
    stViFpnCalibrateInfo.enPixelFormat  = PIXEL_FORMAT_RGB_BAYER_12BPP;
    stViFpnCalibrateInfo.enCompressMode = COMPRESS_MODE_NONE;

    SAMPLE_COMM_VI_FpnCalibrateConfig(ViPipe, &stViFpnCalibrateInfo);

    SAMPLE_PRT("Press Enter key to FPN correction!\n");
    getchar();

    stViFpnCorrectionInfo.enOpType       = OP_TYPE_AUTO;
    stViFpnCorrectionInfo.enFpnType      = stViFpnCalibrateInfo.enFpnType;
    stViFpnCorrectionInfo.u32Strength    = 0;
    stViFpnCorrectionInfo.enPixelFormat  = stViFpnCalibrateInfo.enPixelFormat;
    stViFpnCorrectionInfo.enCompressMode = stViFpnCalibrateInfo.enCompressMode;

    SAMPLE_COMM_VI_FpnCorrectionConfig(ViPipe, &stViFpnCorrectionInfo);

    PAUSE();

    SAMPLE_COMM_VI_DisableFpnCorrection(ViPipe, &stViFpnCorrectionInfo);

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
EXIT3:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}

HI_S32 SAMPLE_VIO_ResoSwitch(HI_U32 u32VoIntfType)
{
    HI_S32             s32Ret;

    HI_S32             s32ViCnt       = 1;
    VI_DEV             ViDev          = 0;
    VI_PIPE            ViPipe         = 0;
    VI_CHN             ViChn          = 0;
    HI_S32             s32WorkSnsId   = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    SIZE_S             stSize;
    VB_CONFIG_S        stVbConf;
    PIC_SIZE_E         enPicSize;
    HI_U32             u32BlkSize;

    VO_CHN             VoChn          = 0;
    SAMPLE_VO_CONFIG_S stVoConfig;

    WDR_MODE_E         enWDRMode      = WDR_MODE_NONE;
    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;

    VPSS_GRP           VpssGrp        = 0;
    VPSS_GRP_ATTR_S    stVpssGrpAttr;
    VPSS_CHN           VpssChn        = VPSS_CHN0;
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0};
    VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

    /*config vi*/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

    stViConfig.s32WorkingViNum                                   = s32ViCnt;
    stViConfig.as32WorkingViId[0]                                = 0;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = enWDRMode;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = VI_OFFLINE_VPSS_OFFLINE;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = enPixFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = enDynamicRange;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = enVideoFormat;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = enCompressMode;

    if ((stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType != SONY_IMX335_MIPI_4M_30FPS_12BIT)
        && (stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType != SONY_IMX335_MIPI_5M_30FPS_12BIT)
        )
    {
        SAMPLE_PRT("Not Support!\n");
        return HI_SUCCESS;
    }

    /*get picture size*/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size by sensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size failed!\n");
        return s32Ret;
    }

    /*config vb*/
    memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 5;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_12BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 2;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        return s32Ret;
    }

    /*start vi*/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
        goto EXIT;
    }

    /*config vpss*/
    memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate    = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate    = -1;
    stVpssGrpAttr.enDynamicRange                 = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                  = enPixFormat;
    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;
    stVpssGrpAttr.bNrEn                          = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode        = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode        = NR_MOTION_MODE_NORMAL;

    astVpssChnAttr[VpssChn].u32Width                    = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height                   = stSize.u32Height;
    astVpssChnAttr[VpssChn].enChnMode                   = VPSS_CHN_MODE_USER;
    astVpssChnAttr[VpssChn].enCompressMode              = enCompressMode;
    astVpssChnAttr[VpssChn].enDynamicRange              = enDynamicRange;
    astVpssChnAttr[VpssChn].enVideoFormat               = enVideoFormat;
    astVpssChnAttr[VpssChn].enPixelFormat               = enPixFormat;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
    astVpssChnAttr[VpssChn].u32Depth                    = 0;
    astVpssChnAttr[VpssChn].bMirror                     = HI_FALSE;
    astVpssChnAttr[VpssChn].bFlip                       = HI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode        = ASPECT_RATIO_NONE;

    /*start vpss*/
    abChnEnable[0] = HI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    /*vi bind vpss*/
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT2;
    }

    /*config vo*/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enDstDynamicRange = enDynamicRange;
    stVoConfig.enVoIntfType = VO_INTF_BT1120;
    stVoConfig.enIntfSync = VO_OUTPUT_576P50;
    stVoConfig.enPicSize = PIC_D1_PAL;

    /*start vo*/
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT3;
    }

    /*vpss bind vo*/
    s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT4;
    }

    printf("switch to 4M========\n");
    getchar();

    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
    SAMPLE_COMM_VI_SwitchMode_StopVI(&stViConfig);

    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SONY_IMX335_MIPI_4M_30FPS_12BIT;

    SAMPLE_COMM_VI_SwitchMode(&stViConfig);


    stVpssGrpAttr.u32MaxW                        = 2592;
    stVpssGrpAttr.u32MaxH                        = 1536;

    astVpssChnAttr[VpssChn].u32Width             = 2592;
    astVpssChnAttr[VpssChn].u32Height            = 1536;

    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    printf("switch to 5M 30fps========\n");
    getchar();

    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
    SAMPLE_COMM_VI_SwitchMode_StopVI(&stViConfig);

    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType = SENSOR0_TYPE;

    SAMPLE_COMM_VI_SwitchMode(&stViConfig);

    stVpssGrpAttr.u32MaxW                        = stSize.u32Width;
    stVpssGrpAttr.u32MaxH                        = stSize.u32Height;

    astVpssChnAttr[VpssChn].u32Width             = stSize.u32Width;
    astVpssChnAttr[VpssChn].u32Height            = stSize.u32Height;

    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto EXIT1;
    }

    PAUSE();

    SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);

EXIT4:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT3:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
EXIT2:
    SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();
    return s32Ret;
}



/******************************************************************************
* function : show usage
******************************************************************************/
void SAMPLE_VIO_Usage(char *sPrgNm)
{
    printf("Usage : %s <index>\n", sPrgNm);
    printf("index:\n");
    printf("\t 0)VI (Online) - VPSS(Online) - VO.\n");
    printf("\t 1)VI (Offline)- VPSS(Online) - VO. LDC+Rotation\n");
    printf("\t 2)VI (Online) - VPSS(Offline)- VO. ISP_DIS\n");
    printf("\t 3)WDR(Online) - VPSS(Offline)- VO. WDR/Line Switch (only for GK7205V300 GK7605V100)\n");
    printf("\t 4)WDR(Offline)- VPSS(Offline)- VO. 4M (only for GK7205V300 GK7605V100)\n");
    printf("\t 5)FPN Calibrate & Correction.\n");
    printf("\t 6)WDR(FrameMode)- VPSS(Offline)- VO.\n");
    return;
}

/******************************************************************************
* function    : main()
* Description : main
******************************************************************************/
#ifdef __HuaweiLite__
int app_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
    HI_S32 s32Ret = HI_FAILURE;
    HI_S32 s32Index;
    HI_U32 u32VoIntfType = 0;
    pthread_t discover_pri_dev = 0;
    pthread_t vio = 0;
    pthread_t time_service = 0;

    if (argc < 2 || argc > 2)
    {
        SAMPLE_VIO_Usage(argv[0]);
        return HI_FAILURE;
    }

#ifndef __HuaweiLite__
    signal(SIGINT, SAMPLE_VIO_HandleSig);
    signal(SIGTERM, SAMPLE_VIO_HandleSig);
    signal(SIGKILL, SAMPLE_VIO_HandleSig);
#endif
    struct timeval tv5;
    struct tm *pLocalTime;
    time_t timep;
    #if 0
    while(1) {
                gettimeofday(&tv5, NULL);
                time(&timep);
                timep += 8*60*60; //utc-->beijing
                pLocalTime = localtime(&timep);
                printf("%04d-%02d-%02d ",   1900+pLocalTime->tm_year, 1+pLocalTime->tm_mon, pLocalTime->tm_mday);
                printf("%02d:%02d:%02d:%03d\n", pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv5.tv_usec / 1000);
                usleep(500);
            }
    #endif
    g_rtsplive = create_rtsp_demo(554);
	session= create_rtsp_session(g_rtsplive,"/mainstream");

    u32VoIntfType = 0;
    pthread_create(&vio , 0, vio_process,  NULL);
    //pthread_create(&discover_pri_dev , 0, discovery_private_device,  NULL);
    //pthread_create(&time_service , 0, timer_server,  NULL);
    http_init();
    while(1) {
        usleep(100);
    }
    s32Index = atoi(argv[1]);
    switch (s32Index)
    {
        case 0:
            s32Ret = SAMPLE_VIO_ViOnlineVpssOnlineRoute(u32VoIntfType);
            break;

        case 1:
            s32Ret = SAMPLE_VIO_ViOfflineVpssOnline_LDC_Rotation(u32VoIntfType);
            break;

        case 2:
            s32Ret = SAMPLE_VIO_ViOnlineVpssOffline_ISPDIS(u32VoIntfType);
            break;

        case 3:
            s32Ret = SAMPLE_VIO_ViWdrSwitch(u32VoIntfType);
            break;

        case 4:
            s32Ret = SAMPLE_VIO_ViWdrOffline(u32VoIntfType);
            break;

        case 5:
            s32Ret = SAMPLE_VIO_FPN(u32VoIntfType);
            break;
        case 6:
            s32Ret = SAMPLE_VIO_FrameModeWdr(u32VoIntfType);
            break;

        default:
            SAMPLE_PRT("the index %d is invaild!\n",s32Index);
            //SAMPLE_VIO_Usage(argv[0]);
            while(1) {
                gettimeofday(&tv5, NULL);
                time(&timep);
                timep += 8*60*60; //utc-->beijing
                pLocalTime = localtime(&timep);
                printf("%04d-%02d-%02d ",   1900+pLocalTime->tm_year, 1+pLocalTime->tm_mon, pLocalTime->tm_mday);
                printf("%02d:%02d:%02d:%03d\n", pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec, tv5.tv_usec / 1000);
                usleep(500);
            }
            return HI_FAILURE;
    }

    if (HI_SUCCESS == s32Ret)
    {
        SAMPLE_PRT("sample_vio exit success!\n");
    }
    else
    {
        SAMPLE_PRT("sample_vio exit abnormally!\n");
    }

    return s32Ret;
}



#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
